Intereting Posts
Установите яркость / контрастность в видеозахвате с помощью Android Camera2 Информация о пользователе из ВКонтакте в Android AsyncTaskLoader onLoadFinished с ожидающей задачей и изменением конфигурации Как запустить диалог «Подключиться к устройству» при использовании пользовательской кнопки каста? Почему я не могу использовать аннотации Override на Android? Получить контакт Фото на основе Contact PhoneNumber Android – Рабочий пример Как сделать Android Spinner с исходным текстом «Выбрать один», Android-приложение, создающее два значка запуска Можете ли вы поделиться ресурсами через APK? Android PagerView между действиями Android закрывает дочернюю активность от родительской активности Должен ли я использовать Сервис или IntentService? Как искать файлы на SD-карте телефона, или где Плагин сканера штрих-кода Zxing для Android-телефона, не работающего на Nexus 7, который имеет только переднюю камеру Поворот изображения в opencv в зависимости от угла наклона …!

Android: CursorLoader сбой на не верхнем фрагменте

У меня есть несколько ListFragments, которые используют CursorLoader для извлечения их содержимого. По мере того, как пользователь перебирает содержимое, один фрагмент заменяет другой (активность остается прежней). Но если контент изменяется на не-верхнем фрагменте, приложение вылетает:

E/AndroidRuntime(18830): FATAL EXCEPTION: main E/AndroidRuntime(18830): java.lang.RuntimeException: Unable to resume activity {com.example.ExampleApp/com.example.ExampleApp.ExampleActivity}: java.lang.IllegalStateException: Content view not yet created E/AndroidRuntime(18830): at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2120) E/AndroidRuntime(18830): at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2135) E/AndroidRuntime(18830): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:957) E/AndroidRuntime(18830): at android.os.Handler.dispatchMessage(Handler.java:99) E/AndroidRuntime(18830): at android.os.Looper.loop(Looper.java:130) E/AndroidRuntime(18830): at android.app.ActivityThread.main(ActivityThread.java:3683) E/AndroidRuntime(18830): at java.lang.reflect.Method.invokeNative(Native Method) E/AndroidRuntime(18830): at java.lang.reflect.Method.invoke(Method.java:507) E/AndroidRuntime(18830): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839) E/AndroidRuntime(18830): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597) E/AndroidRuntime(18830): at dalvik.system.NativeStart.main(Native Method) E/AndroidRuntime(18830): Caused by: java.lang.IllegalStateException: Content view not yet created E/AndroidRuntime(18830): at android.support.v4.app.ListFragment.ensureList(ListFragment.java:328) E/AndroidRuntime(18830): at android.support.v4.app.ListFragment.setListShown(ListFragment.java:280) E/AndroidRuntime(18830): at android.support.v4.app.ListFragment.setListShownNoAnimation(ListFragment.java:266) E/AndroidRuntime(18830): at com.example.ExampleApp.FirstListFragment.onLoadFinished(FirstListFragment.java:102) E/AndroidRuntime(18830): at com.example.ExampleApp.FristListFragment.onLoadFinished(FirstListFragment.java:20) E/AndroidRuntime(18830): at android.support.v4.app.LoaderManagerImpl$LoaderInfo.callOnLoadFinished(LoaderManager.java:414) E/AndroidRuntime(18830): at android.support.v4.app.LoaderManagerImpl$LoaderInfo.reportStart(LoaderManager.java:298) E/AndroidRuntime(18830): at android.support.v4.app.LoaderManagerImpl.doReportStart(LoaderManager.java:751) E/AndroidRuntime(18830): at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:512) E/AndroidRuntime(18830): at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1129) E/AndroidRuntime(18830): at android.app.Activity.performStart(Activity.java:3791) E/AndroidRuntime(18830): at android.app.Activity.performRestart(Activity.java:3821) E/AndroidRuntime(18830): at android.app.Activity.performResume(Activity.java:3826) E/AndroidRuntime(18830): at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2110) E/AndroidRuntime(18830): ... 10 more 

Это может произойти, когда фоновое обновление изменяет содержимое или когда пользователь возвращается с главного экрана, а другой фрагмент находится в верхней части заднего стека. Обработчик onLoadFinished пытается обновить пользовательский интерфейс, который больше не существует. Но почему фрагмент все еще получает обновления курсора?

Я работал над этим, прервав обновление, если фрагмент не виден, но это кажется неправильным.

Вот как выглядит мой Фрагмент, немного отредактированный для краткости:

 public class FirstListFragment extends ListFragment implements LoaderManager.LoaderCallbacks<Cursor> { @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); // Initialize empty cursor adapter. mAdapter = new ExampleCursorAdapter(getActivity(), null, 0); setListAdapter(mAdapter); // Start with a progress indicator setListShown(false); // Prepare the loader. Either re-connect with an existing one, or start a new one. getLoaderManager().initLoader(EXAMPLE_LOADER_ID, null, this); } @Override public Loader<Cursor> onCreateLoader(int id, Bundle args) { return new CursorLoader(getActivity(), ExampleProvider.CONTENT_URI, PROJECTION, null, null, null); } @Override public void onLoadFinished(Loader<Cursor> loader, Cursor data) { // Do nothing if we're not visible. if(!isVisible()) { return; } // Swap the new cursor in. (The framework will take care of closing the // old cursor once we return.) mAdapter.swapCursor(data); // The list should now be shown. if(isResumed()) { setListShown(true); } else { setListShownNoAnimation(true); } } @Override public void onLoaderReset(Loader<Cursor> loader) { // This is called when the last Cursor provided to onLoadFinished() above is about to be // closed. We need to make sure we are no longer using it. mAdapter.swapCursor(null); } } 

isVisible() предотвращает крах, но это ни в одном из примеров кода, который я видел. Что здесь не так?


Edit: Конечно же, я закончил с StaleDataException старым представлением, пытаясь использовать закрытый курсор. Итак, теперь я уничтожаю LoaderManager, когда представление уничтожено. Все еще не уверен, что это правильно, и я не могу воспроизвести исключение StaleDataException.

Я удалил isVisible() взломать сверху и добавил:

 @Override public void onDestroyView() { super.onDestroyView(); // The CursorLoader example doesn't do this, but if we get an update while the UI is // destroyed, it will crash. Why is this necessary? getLoaderManager().destroyLoader(EXAMPLE_LOADER_ID); } 

Кажется, это проблема с фрагментами списка, получающими представление списка. По какой-то причине getListView () не вернет действительный вид, если только фрагмент не показывается. Я видел, как он бросает незаконное государственное исключение на что-либо в жизненном цикле перед onStart ().

То, как я решаю проблему, я вызываю загрузчика в методе onCreateView (). Когда загрузчик возвращается с данными, я проверяю, запускается ли действие. Если это так, я загружаю его в представление списка, если не храню его в локальной переменной, а затем загружаю данные в метод onStart ().

Это похоже на супер-хак, но он работает.