NPE в Fragment.setUserVisibleHint () при использовании ViewPager

Для меня это не так. Я переключаю вкладки вручную в своем ViewPager. У меня этот код внутри моей деятельности:

@Override public void onBackPressed() { if (childFragmentStack.empty()) { // Go to the devices screen Intent intent = new Intent(this, SelectDeviceActivity.class); startActivity(intent); } else { Fragment fragment = childFragmentStack.pop(); if (fragment == null) { return; } processingBackStack = true; if (fragment instanceof ViewChildFragment) { viewFragment.activateFragment((ViewChildFragment) fragment); mViewPager.setCurrentItem(VIEW_FRAGMENT_INDEX, true); } else if (fragment instanceof SetupChildFragment) { setupFragment.activateFragment((SetupChildFragment) fragment); mViewPager.setCurrentItem(SETUP_FRAGMENT_INDEX, true); //** } else if (fragment == homeFragment) { mViewPager.setCurrentItem(HOME_FRAGMENT_INDEX, true); //** } processingBackStack = false; } } 

Если я просматриваю вкладки, я добавляю их в стек («childFragmentStack»). Я использую FragmentPagerAdapter для обработки фрагментов. Что произойдет, если я сделаю что-то вроде View-> Setup-> View-> Setup, а затем отмените его, он дойдет до Setup-> View-> CRASH. Это похоже на то, что я нажимаю «Назад», «Фрагмент настройки» больше не действует для того, что я делаю, но он никогда не воссоздается! Фрагмент установки создается только в MainActivity.onCreate (), поэтому он все равно должен быть рядом и действителен.

NPE происходит на строках, которые я обозначил **. Вот полная трассировка стека:

  04-18 16:04:57.096: E/AndroidRuntime(13072): FATAL EXCEPTION: main 04-18 16:04:57.096: E/AndroidRuntime(13072): java.lang.NullPointerException 04-18 16:04:57.096: E/AndroidRuntime(13072): at android.support.v4.app.Fragment.setUserVisibleHint(Fragment.java:841) 04-18 16:04:57.096: E/AndroidRuntime(13072): at android.support.v4.app.FragmentPagerAdapter.setPrimaryItem(FragmentPagerAdapter.java:130) 04-18 16:04:57.096: E/AndroidRuntime(13072): at android.support.v4.view.ViewPager.populate(ViewPager.java:1066) 04-18 16:04:57.096: E/AndroidRuntime(13072): at android.support.v4.view.ViewPager.setCurrentItemInternal(ViewPager.java:550) 04-18 16:04:57.096: E/AndroidRuntime(13072): at android.support.v4.view.ViewPager.setCurrentItemInternal(ViewPager.java:509) 04-18 16:04:57.096: E/AndroidRuntime(13072): at android.support.v4.view.ViewPager.setCurrentItem(ViewPager.java:501) 04-18 16:04:57.096: E/AndroidRuntime(13072): at com.lochinvar.serf.MainActivity.onBackPressed(MainActivity.java:234) 04-18 16:04:57.096: E/AndroidRuntime(13072): at android.app.Activity.onKeyUp(Activity.java:2131) 04-18 16:04:57.096: E/AndroidRuntime(13072): at android.view.KeyEvent.dispatch(KeyEvent.java:2633) 04-18 16:04:57.096: E/AndroidRuntime(13072): at android.app.Activity.dispatchKeyEvent(Activity.java:2361) 04-18 16:04:57.096: E/AndroidRuntime(13072): at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.java:1819) 04-18 16:04:57.096: E/AndroidRuntime(13072): at android.view.ViewRootImpl.deliverKeyEventPostIme(ViewRootImpl.java:3577) 04-18 16:04:57.096: E/AndroidRuntime(13072): at android.view.ViewRootImpl.handleImeFinishedEvent(ViewRootImpl.java:3547) 04-18 16:04:57.096: E/AndroidRuntime(13072): at android.view.ViewRootImpl$ViewRootHandler.handleMessage(ViewRootImpl.java:2797) 04-18 16:04:57.096: E/AndroidRuntime(13072): at android.os.Handler.dispatchMessage(Handler.java:99) 04-18 16:04:57.096: E/AndroidRuntime(13072): at android.os.Looper.loop(Looper.java:137) 04-18 16:04:57.096: E/AndroidRuntime(13072): at android.app.ActivityThread.main(ActivityThread.java:4745) 04-18 16:04:57.096: E/AndroidRuntime(13072): at java.lang.reflect.Method.invokeNative(Native Method) 04-18 16:04:57.096: E/AndroidRuntime(13072): at java.lang.reflect.Method.invoke(Method.java:511) 04-18 16:04:57.096: E/AndroidRuntime(13072): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786) 04-18 16:04:57.096: E/AndroidRuntime(13072): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553) 04-18 16:04:57.096: E/AndroidRuntime(13072): at dalvik.system.NativeStart.main(Native Method) 

[EDIT] Я забыл упомянуть, что я перегрузил FragmentPagerAdapter.getPageTitle (), и он никогда не возвращает значение null (случай по умолчанию относится к строке).

Solutions Collecting From Web of "NPE в Fragment.setUserVisibleHint () при использовании ViewPager"

В заключение! Теперь я могу надежно воссоздать эту ошибку!

Еще один способ, который я нашел, чтобы воссоздать ошибку, – закрыть активность / приложение и быстро открыть страницу с помощью фрагмента ViewPager. Возможно, вам придется попробовать несколько раз, потому что в моих тестах мне пришлось повторно открывать приложение в течение примерно 30 мс. Это время может быть медленнее или быстрее для разных устройств скорости.

Проблема заключалась в том, что я только однажды создал фрагмент (используя new ) один раз и сохранил ссылку на этот экземпляр, чтобы я мог его повторно использовать. Одно простое решение этой проблемы – всегда возвращать new экземпляр фрагмента FragmentPagerAdapter.getItem(...) , как показано ниже.

 public class ViewPagerAdapter extends FragmentPagerAdapter { ... @Override public Fragment getItem(int position) { switch (position) { case 0: return mMyFragment; // Error. Has the edge-case crash. case 1: return new MyFragment(); // Works. default: return new MyDefaultFragment(); } } } 

Ps – Корневая проблема, вероятно, имеет какое-то отношение к жизненному циклу фрагмента и пытается использовать его снова, пока он уничтожается.

Pps – это решение исправляет NullPointerException для android.app.Fragment.setUserVisibleHint(Fragment.java:997) а также должно работать для android.support.v4.app.Fragment.setUserVisibleHint .

Это было для меня настоящим мозгом. Мы удалили весь код, который заменил Fragment s, и сохранили одни и те же фрагменты для всего жизненного цикла Activity и все еще имели эту проблему. Это было не до тех пор, пока мы не viewPager.setOffscreenPageLimit(TABS); Где TABS – количество вкладок (в нашем случае 4), что мы перестали получать ссылочное NullPointerException .

FWIW. Я уверен, что проблема в коде Google. Мы не смогли заставить это потерпеть неудачу на Nexus 5, работающем с Lollipop, но он не работает на устройствах Samsung, работающих под управлением Kitkat. Когда я проследил эту ошибку, похоже, что сбой происходит, потому что ссылка на Fragment уже прошла через внутреннюю функцию Fragment.initState потому что id Fragment равен -1.

У меня было плохое время в очень похожем случае (такое же исключение в Fragment.setUserVisibleHint ), даже если я использовал FragmentStatePagerAdapter. Был случайный (таким образом, трудно воспроизвести) крах моего приложения, когда базовые данные, которые были изменены.

В моем случае я, наконец, смог избавиться от этого сбоя, переопределив следующий способ в адаптере:

 @Override public void restoreState(Parcelable state, ClassLoader loader) { // don't super ! } 

Я думаю, что в этом классе есть ошибка, учитывая количество вопросов, подобных этому в StackOverflow.

Надеюсь, это может быть полезно кому-то.

Редактировать: я отправил аналогичный ответ на android.support.v4.app.Fragment.setUserVisibleHint нулевой указатель при возобновлении приложения, однако я не уверен, что эти вопросы дублируются. Тем не менее, я думаю, что этот ответ может помочь некоторым людям найти их для подобного симптома. Как я должен это отметить?