Intereting Posts
Отключение анимации в ViewPager Android получить видео thumbnail PATH, а не растровое изображение DownloadManager исключает исключение при загрузке более одного файла Прокрутка больших списков адаптеров на основе курсора выполняется быстрее, чем гораздо меньшие списки адаптеров в памяти Android-микрофон не работает, когда он используется другим приложением в фоновом режиме Экспорт APK из Eclipse создает ошибку «Нет встроенных инструментов, установленных в SDK» Android удаляет панель действий приложения GCM: Как отправить heartbeat на сервер GCM Android подключается к серверу с самоподписанным сертификатом Выполнение javascript в фоновом режиме с использованием телефонной заставки Библиотека дизайна макетов Android Android: как я могу вставить RecyclerView внутри CardView? Что удерживает состояние моей деятельности после того, как мой процесс приложения был убит? Инструмент для создания отчетов об ошибках / библиотека для разработки приложений Отдельные строковые значения Android для выпуска и отладки

AsyncTask, Фрагменты, Представления и Backstacks

Я немного использовал этот шаблон. Вот очень надуманный пример индикатора прогресса AsyncTask +:

new AsyncTask<Void, Void, Void>() { WeakReference<MyFragment> weakFragment = new WeakReference<MyFragment>(MyFragment.this); @Override protected void onPreExecute() { Fragment fragment = weakFragment.get(); if(fragment != null) fragment.getView().findViewById(R.id.progress).setVisibility(View.VISIBLE); } @Override protected Document doInBackground(Void... params) { Fragment fragment = weakFragment.get(); if(fragment == null) return null; // Do something ... } @Override protected void onPostExecute() { Fragment fragment = weakFragment.get(); if(fragment != null) fragment.getView().findViewById(R.id.progress).setVisibility(View.GONE); } }.execute(); 

Он работает нормально с изменениями ориентации, но я заметил, что фрагмент не равен null, а фрагмент.getView () является нулевым, когда я выталкиваю фрагмент из задней части. Это, очевидно, заставляет это рухнуть. Какой подход вы используете? Я не могу найти идеальное решение в Интернете. Важно отметить, что это фрагмент, и я вызываю setRetainInstance(true); На этом фрагменте в его onActivityCreated (…).

AsyncTask – это асинхронная задача, которая означает, что вы обычно не знаете, когда она будет завершена, и когда она вызывает onPostExecute() . Я думаю, ваша проблема здесь. Когда вы поворачиваете свое устройство, ваша асинтеза еще не закончилась, а вид фрагмента уничтожен и снова воссоздается очень быстро, в то время как асинтектура находится в рабочем потоке, и когда она выполнила свое задание, у вашего фрагмента есть представление, а возвращаемое значение getView не null . Но если время вращения займет много, вы получите null потому что AsyncTask закончен, но у вашего фрагмента нет никакого представления. Теперь этот сценарий происходит именно с вашей задней стопой. Когда вы нажимаете фрагмент на заднюю часть, его представление уничтожается ( смотрите изображение ), но сам фрагмент отсутствует (фрагмент возвращается к макету из backstack). Теперь ваш AsyncTask завершает работу и вызывает метод getView fragment и доза не имеет никакого view поэтому вы получите NPE .

Мое решение:

Сначала вы должны использовать WeakReference<ProgressBar> вместо WeakReference<MyFragment> и в onPostExecute() проверить, является ли оно нулевым или нет, если оно равно null, ничего не делать, поскольку значение по умолчанию невидимо, если оно не является нулевым вызовом setVisibility(View.GONE) .

Обновить:

Фрагмент жив, но взгляд был dealloc'd. Это возможно?

Да, просто посмотрите на рисунок 2 по ссылке. Когда фрагмент активен (зеленый квадрат), the fragment added to back stack фрагменту the fragment added to back stack переходит в onPause , onStop onDestroyView . Затем, когда фрагмент выскакивает из заднего стека, он идет прямо в onCreateView со ссылкой на стрелку с этим текстом: the fragment returns to the layout from backstack .

Чтобы подтвердить свой ответ, вы можете создать AsyncTask и вызвать SystemClock.sleep(30000) внутри вашего doInbackground . Теперь вы можете подтолкнуть свой фрагмент к backstack и вытащить его из backstack без исключения, потому что asynctask еще не закончил и когда он вызовет onPostExecute() ваш фрагмент уже имеет представление.

Еще одна хорошая вещь, которую вы можете увидеть, – setRetainInstance

Это можно использовать только с фрагментами, не входящими в задний стек.

Поэтому, когда вы нажимаете свой фрагмент на задний стек, он может полностью уничтожаться, и вы можете получить новую ссылку на фрагмент, когда она появится. Но когда вы используете setRetainInstance(true); Для изменений конфигурации ваш фрагмент сохраняется во время повторного создания Activity, что означает, что это тот же самый фрагмент, и onCreate не вызывается. И это очень важно, потому что если вы запустите свой AsyncTask в методе onCreate , когда вы нажмете свой фрагмент в задний стек и выскочите его, у вас может появиться новый фрагмент, и это значит, onCreate метод onCreate запущен, а другой AsyncTask запущен. Это означает, что у вас нет никакого контроля над количеством вызовов AsyncTask поэтому следите за утечками памяти!