Intereting Posts
Многопоточная правильность: использование синхронизированного блока Image background – как повторять изображение как фон, а не растягивать его Ошибка при добавлении CardView в макет Проверка URL-адресов работает нормально, но поддерживает соединение и ограничивает дальнейшие запросы Как связать несколько методов GroupBy () RxJava, таких как groupBy (). GroupBy () Советы по организации крупных проектов Android? Официальная «Boost library» Поддержка Android и iOS? Предоставить разрешение uri на uri в EXTRA_STREAM с намерением AnimateLayoutChanges не работает с RecyclerView Что такое объявление adb -l? Android 4.3 с Genymotion uvesafb: не удалось выполнить / sbin / v86d Как предотвратить изменение размера EditText при вводе пользователем? Галерея setSelection не запускает селектор изображений Перечислите активность с помощью заголовка, нижнего колонтитула и опустошите все видимые Как я могу показать новый фрагмент в одной вкладке?

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 ().

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