1

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/LayoutFragment( 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?

Fabian
  • 933
  • 1
  • 10
  • 14

3 Answers3

3

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 :)

Geoff
  • 2,822
  • 1
  • 19
  • 14
  • 1
    Your my hero :) I think it's worth mentioning that you don't have to import the sources into your project as the visibility of needed members is set to default. Just create an android.support.v4.app package in your src and a class that extends FragmentActivity. This will be enough to provide access to mResumed and mFragments. – dskinner May 30 '12 at 17:11
0

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.

dskinner
  • 9,259
  • 1
  • 27
  • 41
  • ppl, you should disregard this as this doesn't work on all android versions – dskinner May 30 '12 at 17:15
  • i get a completely different log info for some reason.... http://stackoverflow.com/questions/11104727/so-why-does-my-log-info-shows-completely-wrong-behaviour-between-activity-fragm – Maxrunner Jun 19 '12 at 16:12
0

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.

dokkaebi
  • 8,294
  • 3
  • 38
  • 58