Search code examples
androidandroid-listfragment

setAdapter() in fragment's onActivityCreated causes "IllegalStateException: Content view not yet created" when hitting Back button


When my app is running in single-column mode, tapping on an item in ListFragment A uses a callback to the main Activity to programatically launch Fragment B to display additional information. I launch Fragment B in this manner:

// Create the new fragment and set an argument pointing to the entry's ID in the database
FragmentEntryDetails newFragment = new FragmentEntryDetails();
Bundle args = new Bundle();
args.putInt("entryID", entryID);
newFragment.setArguments(args);

// Specify where in the view we want to place the fragment, then add it to the backstack so the user can
// return to the previous fragment
FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.replace(R.id.fragment_container, newFragment);
transaction.addToBackStack(null);
// Commit the transaction
transaction.commit();

When I hit the Back button to return to the list of search results in ListFragment A, the app crashes with the following IllegalStateException:

03-06 09:21:53.273: E/AndroidRuntime(32760): FATAL EXCEPTION: main
03-06 09:21:53.273: E/AndroidRuntime(32760): java.lang.IllegalStateException: Content view not yet created
03-06 09:21:53.273: E/AndroidRuntime(32760):    at android.app.ListFragment.ensureList(ListFragment.java:386)
03-06 09:21:53.273: E/AndroidRuntime(32760):    at android.app.ListFragment.getListView(ListFragment.java:280)
03-06 09:21:53.273: E/AndroidRuntime(32760):    at com.test.dictApp.FragmentSearch.onActivityCreated(FragmentSearch.java:98)
03-06 09:21:53.273: E/AndroidRuntime(32760):    at android.app.Fragment.performActivityCreated(Fragment.java:1703)
03-06 09:21:53.273: E/AndroidRuntime(32760):    at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:903)
03-06 09:21:53.273: E/AndroidRuntime(32760):    at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1057)
03-06 09:21:53.273: E/AndroidRuntime(32760):    at android.app.BackStackRecord.popFromBackStack(BackStackRecord.java:764)
03-06 09:21:53.273: E/AndroidRuntime(32760):    at android.app.FragmentManagerImpl.popBackStackState(FragmentManager.java:1484)
03-06 09:21:53.273: E/AndroidRuntime(32760):    at android.app.FragmentManagerImpl.popBackStackImmediate(FragmentManager.java:490)
03-06 09:21:53.273: E/AndroidRuntime(32760):    at android.app.Activity.onBackPressed(Activity.java:2167)
03-06 09:21:53.273: E/AndroidRuntime(32760):    at android.app.Activity.onKeyUp(Activity.java:2145)
03-06 09:21:53.273: E/AndroidRuntime(32760):    at android.view.KeyEvent.dispatch(KeyEvent.java:2633)
03-06 09:21:53.273: E/AndroidRuntime(32760):    at android.app.Activity.dispatchKeyEvent(Activity.java:2375)
03-06 09:21:53.273: E/AndroidRuntime(32760):    at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.java:1847)
03-06 09:21:53.273: E/AndroidRuntime(32760):    at android.view.ViewRootImpl.deliverKeyEventPostIme(ViewRootImpl.java:3701)
03-06 09:21:53.273: E/AndroidRuntime(32760):    at android.view.ViewRootImpl.handleImeFinishedEvent(ViewRootImpl.java:3651)
03-06 09:21:53.273: E/AndroidRuntime(32760):    at android.view.ViewRootImpl$ViewRootHandler.handleMessage(ViewRootImpl.java:2818)
03-06 09:21:53.273: E/AndroidRuntime(32760):    at android.os.Handler.dispatchMessage(Handler.java:99)
03-06 09:21:53.273: E/AndroidRuntime(32760):    at android.os.Looper.loop(Looper.java:137)
03-06 09:21:53.273: E/AndroidRuntime(32760):    at android.app.ActivityThread.main(ActivityThread.java:5041)
03-06 09:21:53.273: E/AndroidRuntime(32760):    at java.lang.reflect.Method.invokeNative(Native Method)
03-06 09:21:53.273: E/AndroidRuntime(32760):    at java.lang.reflect.Method.invoke(Method.java:511)
03-06 09:21:53.273: E/AndroidRuntime(32760):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
03-06 09:21:53.273: E/AndroidRuntime(32760):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
03-06 09:21:53.273: E/AndroidRuntime(32760):    at dalvik.system.NativeStart.main(Native Method)

The error points to setAdapter() in ListFragment A's onActivityCreated() function:

@Override
public void onActivityCreated(Bundle savedInstanceState)
{
    // Tell the main activity that this fragment has menu elements to declare
    super.onActivityCreated(savedInstanceState);
    setHasOptionsMenu(true);

    adapter = new FragmentSearchCursorAdapter(getActivity(), null, 0);
    // Assign our CursorAdapter
    getListView().setAdapter(adapter);

    Bundle args = getSQLArgs("dictionary");
    // Load up the cursor that will handle the SQL grunt work
    getLoaderManager().initLoader(SEARCH_LOADER_ID, args, this);
}

Why is getListView().setAdapter() causing a problem? According to the Fragment lifecycle, the listView should be available for manipulation. Should I only be setting the adapter if it hasn't already been set?

Edit: I figured it out, see my Answer below.


Solution

  • I just recently earned enough credit to answer my own questions, so I've decided to turn my comments into an actual Answer.

    The solution was to move the assignment of my FragmentSearchCursorAdapter to ListFragment A's onCreateView() method, and then use setListAdapter() instead of getListView().setAdapter(), as below:

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    {
        // Specify the fragment layout file for this fragment class
        View view = inflater.inflate(R.layout.fragment_search, container, false);
        // Assign our CursorAdapter
        adapter = new FragmentSearchCursorAdapter(getActivity(), null, 0);
        setListAdapter(adapter);
    
        return view;
    }