App crash after activity has been killed in background

After doing some research, it seems that the problem stems from the misnaming of FragmentPagerAdapter‘s method – being named getItem(), but not clearly specifying that the abstract method getItem(int position) is supposed to return a new instance of a fragment rather than just “get an instance of one”.

Of course, there is not much we can do about an incorrect name after it’s been out in the wild for 7 years, but at least we can fix the bug that stems from this issue in your code 😉


Without further ado, the cause of your NPE is that onCreateView (where your Presenter is instantiated) is never called.

This happens because you are creating the fragment here:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    setContentView(R.layout.activity_main)
    ...
    homeFragment = HomeScreenFragment.newInstance()
    incidentFragment = IncidentScreenFragment.newInstance()
}

You return this fragment from inside getItem(int position) in your FragmentPagerAdapter:

override fun getItem(position: Int): Fragment = when(position) {
     ...
     1 -> activity.incidentFragment
     ...
}

So what we know about activity.incidentFragment is that in it, onCreateView() is never called.

This is caused by the fact that it’s never actually added to a FragmentManager and never displayed on the screen.

That’s because super.onCreate(savedInstanceState) in Activity recreates all Fragments, using their no-args constructor, via reflection, while keeping their tag (see findFragmentByTag).

So as you can see in this answer, or as I can quote here:

    // Do we already have this fragment?
    String name = makeFragmentName(container.getId(), itemId);
    Fragment fragment = mFragmentManager.findFragmentByTag(name);
    if (fragment != null) {
        if (DEBUG) Log.v(TAG, "Attaching item #" + itemId + ": f=" + fragment);
        mCurTransaction.attach(fragment);
    } else {
        fragment = getItem(position);
        if (DEBUG) Log.v(TAG, "Adding item #" + itemId + ": f=" + fragment);
        mCurTransaction.add(container.getId(), fragment,
                makeFragmentName(container.getId(), itemId));

The getItem(position) method is only called if the Fragment is not found by the fragment tag that the FragmentPagerAdapter sets for the fragment, which IS automatically recreated after low memory condition kills your app.

Therefore, YOUR new fragment (that you create by hand in the Activity) is NEVER used, and therefore it has no view, never initialized, never added to FragmentManager, it’s not the same instance as what’s actually inside your ViewPager, and it crashes when you call it. Boom!



Solution is to instantiate the Fragment inside FragmentPagerAdapter’s getItem(position) method. To get an instance of the fragment, use this answer.

Leave a Comment