Intereting Posts
Android NDK UnsatisfiedLinkError – удивительная причина Вертикальный центрирующий текст с надписью на Android-кнопках Говоря с модемом с AT-командами на Android Запустить Android OpenGL в фоновом режиме, как рендеринг ресурсов для приложения? Есть ли простой способ добавить границу к верхней и нижней части Android View? Как рассчитать покрытие при использовании Robolectric Android – затмение FileExplorer как root Конфигурация с именем «по умолчанию» не найдена. Android Studio Получить фоновый доступный вид Автоматически настроить размер текста, чтобы он соответствовал кнопке Android Android Espresso – нажмите на элемент навигационного элемента с изображением и текстом Отсутствие экспертного сертификата Exception – Volley и Android с самоподписанным сертификатом Ошибка при создании нового проекта в студии android Каков правильный способ обработки подписки в RxJava / RxAndroid для жизненного цикла активности? Android: установить элемент списка списка как «выбранный» (выделено)

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); } 

Solutions Collecting From Web of "Android: CursorLoader сбой на не верхнем фрагменте"

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

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

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