NPE in Fragment.setUserVisibleHint() when using ViewPager

android, android-fragments

Solution

Finally! I'm now able to reliably recreate this error!

Another way that I found to recreate error is to close activity/app, and quickly reopen page with the ViewPager fragment. You may have to try a few times because in my tests I had to reopen the app within about 30ms. This time may be slower or faster for different speed devices.

The problem was that I only explicitly created the Fragment (using `new`) once, and kept a reference to that instance so that I could reuse it. One simple fix to this problem is to always return a `new` instance of the Fragment the `FragmentPagerAdapter.getItem(...)`, as shown below.

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 - The root problem likely has something to do with the Fragment lifecycle and trying to use it again while it's being destroyed.

pps - This solution fixes the NullPointerException for `android.app.Fragment.setUserVisibleHint(Fragment.java:997)` and should also work for `android.support.v4.app.Fragment.setUserVisibleHint`.

Problem

I am at a loss for this. I am switching tabs manually in my ViewPager. I have this code inside my Activity: ``` @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; } } ``` If I scroll between tabs I add them to a Stack (the 'childFragmentStack'). I am using FragmentPagerAdapter to handle the fragments. What happens is if I do something like View->Setup->View->Setup and then reverse it, it only gets as far as Setup->View->CRASH. It's like when I press Back the Setup Fragment is no longer valid for what I'm doing, but it is never recreated! The Setup fragment is only created in MainActivity.onCreate(), so it should still be around and valid. The NPE happens on the lines I marked **. Here is the full stack trace: ``` 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] I forgot to mention I overrode FragmentPagerAdapter.getPageTitle() and it never returns null (default case goes to a string).

Original source

Related problems