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.
精彩评论