开发者

Android Fragment Lifecycle of Single Instance Activity

I have a singleInstance Activity and a Fragment which I instantiate in the onCreate() method and add into a FrameLayout container into the layout of the activity. The activity does nothing except printing out the logs. I am using the android-support-v4 lib and android 2.3.3.

I observed a strange lifecycle behavior with this setting and I wonder if you might help me to explain this. I will provide the logs for the lifecycles:

First call of the activity:

    07-07 15:12:17.990 V/FragActivity( 2358): onCreate >> com.test.fragmentlife.FragActivity@44f98778
    07-07 15:12:21.010 V/FragActivity( 2358): onCreate <<
    07-07 15:12:21.020 V/LayoutFragment( 2358): onAttach > LayoutFragment{44f467c8 #0 id=0x7f070000}
    07-07 15:12:24.021 V/LayoutFragment( 2358): onAttach <
    07-07 15:12:24.021 V/LayoutFragment( 2358): onCreate > LayoutFragment{44f467c8 #0 id=0x7f070000}
    07-07 15:12:27.020 V/LayoutFragment( 2358): onCreate <
    07-07 15:12:27.020 V/LayoutFragment( 2358): onCreateView > LayoutFragment{44f467c8 #0 id=0x7f070000}
    07-07 15:12:30.022 V/LayoutFragment( 2358): onCreateView <
    07-07 15:12:30.030 V/LayoutFragment( 2358): onActivityCreated > LayoutFragment{44f467c8 #0 id=0x7f070000}
    07-07 15:12:33.030 V/LayoutFragment( 2358): onActivityCreated <
    07-07 15:12:33.030 V/LayoutFragment( 2358): onStart > LayoutFragment{44f467c8 #0 id=0x7f070000}
    07-07 15:12:36.030 V/LayoutFragment( 2358): onStart <
    07-07 15:12:36.040 V/FragActivity( 2358): onStart > com.test.fragmentlife.FragActivity@44f98778
    07-07 15:12:39.041 V/FragActivity( 2358): onStart <
    07-07 15:12:39.041 V/LayoutFragment( 2358): onStop > LayoutFragment{44f467c8 #0 id=0x7f070000}
    07-07 15:12:42.040 V/LayoutFragment( 2358): onStop <
    07-07 15:12:42.040 V/FragActivity( 2358): onResume > com.test.fragmentlife.FragActivity@44f98778
    07-07 15:12:45.041 V/FragActivity( 2358): onResume <
    07-07 15:12:45.041 V/LayoutFragment( 2358): onStart > LayoutFragment{44f467c8 #0 id=0x7f070000}
    07-07 15:12:48.040 V/LayoutFragment( 2358): onStart <
    07-07 15:12:48.040 V/LayoutFragment( 2358): onResume > LayoutFragment{44f467c8 #0 id=0x7f070000}
    07-07 15:12:51.042 V/LayoutFragment( 2358): onResume <

First question: why is the onStop() method of the fragment during the creation of the activity? The Fragment displays fine on the screen.

After that I restart the activity by firing an intent, causing the onNewIntent() lidecycle method of the activity.

    07-07 15:13:17.220 V/LayoutFragment( 2358): onPause > LayoutFragment{44f467c8 #0 id=0x7f070000}
    07-07 15:13:20.220 V/L开发者_JAVA技巧ayoutFragment( 2358): onPause <
    07-07 15:13:20.230 V/FragActivity( 2358): onPause > com.test.fragmentlife.FragActivity@44f98778
    07-07 15:13:23.231 V/FragActivity( 2358): onPause <
    07-07 15:13:23.231 V/FragActivity( 2358): onNewIntent > com.test.fragmentlife.FragActivity@44f98778
    07-07 15:13:26.231 V/FragActivity( 2358): onNewIntent <
    07-07 15:13:26.231 V/FragActivity( 2358): onResume > com.test.fragmentlife.FragActivity@44f98778
    07-07 15:13:29.230 V/FragActivity( 2358): onResume <

Second question: why is the onResume() method of the fragment not called? It is still visible on the screen. As far as i know activity and lifecycle methods should go hand in hand...

After that i restart the activity a second time:

    07-07 15:13:42.140 V/FragActivity( 2358): onPause > com.test.fragmentlife.FragActivity@44f98778
    07-07 15:13:45.143 V/FragActivity( 2358): onPause <
    07-07 15:13:45.143 V/FragActivity( 2358): onNewIntent > com.test.fragmentlife.FragActivity@44f98778
    07-07 15:13:48.144 V/FragActivity( 2358): onNewIntent <
    07-07 15:13:48.150 V/FragActivity( 2358): onResume > com.test.fragmentlife.FragActivity@44f98778
    07-07 15:13:51.151 V/FragActivity( 2358): onResume <

Now the lifecycle methods of the fragmen are not triggered at all.. how is that?


I can't answer question 1, although I've noticed that behavior as well, but I rarely do much work in my onStop methods (I favor onPause and onResume), I can help with your 2nd question.

The problem here (which is definitely a google bug) is either a problem with FragmentActivity or the Activity lifecycle as a whole (depending on how you look at it).

Basically, the FragmentActivity moves its fragments to the resumed state, not in the onResume method (as a generally sane person might think) but in the onPostResume method. This is all well and good, except that the onPostResume method never gets called in a singleIntstance/singleTask activity when the activity is recalled with onNewIntent.

So what I did (having imported the support package code, instead of just the jar) was modify FragmentActivity like so...

//this boolean is only ever set to true in onNewIntent
private boolean mResumeNeedsToDoDispatch = false; 

/**
 * Ensure any outstanding fragment transactions have been committed.
 */
@Override
protected void onResume() {
    super.onResume();
    mResumed = true;

    //Check if onNewIntent was called. If so, dispatch resumes to fragments now
    if (mResumeNeedsToDoDispatch) {
        mResumeNeedsToDoDispatch = false;
        mFragments.dispatchResume();
    }

    mFragments.execPendingActions();
}


/**
 * Google, I think you forgot this #(
 */
@Override
public void onNewIntent(Intent newIntent) {
    super.onNewIntent(newIntent);
    mResumeNeedsToDoDispatch = true;
}

Notice that I didn't just call mFragments.dispatchResume() in onNewIntent cause this causes the fragment onResume methods to be called twice in this case. I'm not 100% sure why that is, but that is what I noticed in my tests.

Hope this helps :)


This led me to a related discovery --

I have a fragment that is inflated from an xml tag. On a Xoom running 3.2.1, things work as expected. On a Galaxy 10.1 running 3.1, the fragment's onResume method is never called. Looks like the fix may have been added in 3.2.


I just want to add to Geoff's comment, in my particular case I was recreating a set of nested fragments when onNewIntent was fired, and for it to successfully work, I setup a class member mShouldUpdateFragments, setting it true in onNewIntent, and overriding onPostResume where I did my work based on the boolean.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜