android compatibility package – fragment … not attached to Activity-ThrowExceptions

Exception or error:

Hello,
I’m facing this problem :
I’m using Compatibility package to use fragment in android application (min SDK 2.1).

An random exception occurs on fragment sometimes and I can’t figure out why.
This is the stack trace I receive:

java.lang.IllegalStateException: Fragment FeedListFragment{438a54e8} not attached to Activity
    at android.support.v4.app.Fragment.getLoaderManager(Fragment.java:715)
    at com.myappli.ui.FeedListFragment.refreshUpdateDate(FeedListFragment.java:283)
    at com.myappli.ui.phone.FeedListActivity.onReceiveResult(FeedListActivity.java:277)
    at com.myappli.data.rssplayer.service.KTDetachableResultReceiver.onReceiveResult(KTDetachableResultReceiver.java:55)
    at android.os.ResultReceiver$MyRunnable.run(ResultReceiver.java:43)
    at android.os.Handler.handleCallback(Handler.java:587)
    at android.os.Handler.dispatchMessage(Handler.java:92)
    at android.os.Looper.loop(Looper.java:136)
    at android.app.ActivityThread.main(ActivityThread.java:4425)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:521)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
    at dalvik.system.NativeStart.main(Native Method)

Here is the corresponding code I’m calling in the Fragment class:

public class FeedListFragment extends ListFragment implements LoaderManager.LoaderCallbacks<Cursor>, FeedListCursorAdapterListener {

...
    public void refreshUpdateDate() {
    getLoaderManager().restartLoader(LAST_UPDATE_CURSOR_ID, null, this);
    }
...
}

Here is the code of the activity that calls the fragment:

private FeedListFragment mCursorLoaderListFg;

if (!isFinishing()) {
    mCursorLoaderListFg.refreshUpdateDate();
    mCursorLoaderListFg.refreshDisplay();
    mCursorLoaderListFg.hideLoadingArticles();
}

Here is the fragment source code for getLoaderManager():

/**
* Return the LoaderManager for this fragment, creating it if needed.
*/
public LoaderManager getLoaderManager() {
    if (mLoaderManager != null) {
        return mLoaderManager;
    }
    if (mActivity == null) {
        throw new IllegalStateException("Fragment " + this + " not attached to Activity");
    }
    mCheckedForLoaderManager = true;
    mLoaderManager = mActivity.getLoaderManager(mIndex, mLoadersStarted, true);
    return mLoaderManager;
}

Here are the steps of the application before crash:

  1. The activity calls methods in background.
  2. Callback methods are called on the activity
  3. In this callback method, the activity calls the fragment
  4. The fragment tries to launch some methods (like getLoadManager()) that need activity.
  5. The fragment is not attached anymore to the activity => crash

We tried two fixes:

  • test on activity to check if the activity is finishing (like the code above)
  • test on the fragment with the method isDetached.

Thanks for your help!!!

Do not hesitate to ask me more information if I’m not clear.

How to solve:

I had a similar problem.

Try using isAdded() or isVisible() instead of isDetached(). Unfortunately, isDetached() doesn’t seem to work like it should…

###

What that worked for me was to use the Fragment listener of the fragment, add a getActivity function for it that returns the activity of the Fragment listener (the activity that created the fragment).

Now when i have a call that needed the activity i just use the function.

###

I resolved this issue by changing my inner adapter class to static inner class.

private static class MessagesAdapter extends CursorAdapter {
...

I am not sure how to explain that but it’s related to the fact that we should avoir using non static inner class as recommended here

###

The fragment will be attached to the activity on the event Fragment.onAttach(Activity). Your Activity has to implement a listener, the Fragment provides.
To ensure that your method refreshUpdateDate() will be called only after the event, onAttach() should first take the activity as listener implementation and then call the listener fragmentAttached() method. So your activity will be informed, when the fragment is attached and refreshUpdateDate() can be called, for instance direct in fragmentAttached().
See Creating event callbacks to the activity.

Leave a Reply

Your email address will not be published. Required fields are marked *