59

I'm using FragmentActivity and Fragments.

When the application starts:

FragmentActivity onCreate() <------
FragmentActivity onStart()
FragmentActivity onResume()
Fragment onAttach()
Fragment onCreate() <------
Fragment onCreateView()
Fragment onActivityCreated()
Fragment onStart()
Fragment onResume()

Everything is OK, FragmentActivity onCreate() is called before Fragment onCreate(). And when I rotate:

Fragment onPause()
FragmentActivity onPause()
Fragment onStop()
FragmentActivity onStop()
Fragment onDestroyView()
Fragment onDestroy()
Fragment onDetach()
FragmentActivity onDestroy()
---
Fragment onAttach()
Fragment onCreate() <----------
FragmentActivity onCreate() <---------
Fragment onCreateView()
Fragment onActivityCreated()
Fragment onStart()
FragmentActivity onStart()
FragmentActivity onResume()
Fragment onResume()

Fragment onCreate() is called before FragmentActivity onCreate(). Why is it inconsistent?

In FragmentActivity onCreate() I generate some data, which Fragment onCreate() gets. Because of that strange behaviour I had to move my code from Fragment onCreate() to Fragment onCreateView() to be sure that my data had been generated before.

I'm using FragmentStatePagerAdapter to hold Fragments, maybe that is the reason?

AppiDevo
  • 3,195
  • 3
  • 33
  • 51
  • So, what's your solution? – levi Aug 28 '14 at 16:53
  • @levi Populate your Views with data in onActivityCreated() Fragment's method. Or rethink your architecture, in most cases you don't have to get your data from the host activity. And use Loaders if you have ListView/RecyclerView with dynamic data. That was my final solution because I had List in every fragment. You can also use message bus library (EventBus, Otto, ...) to have even cleaner architecture. – AppiDevo Mar 15 '17 at 09:06

2 Answers2

66

You should not count on a valid Activity until the onActivityCreated() call in the Fragment's life cycle.

Called when the fragment's activity has been created and this fragment's view hierarchy instantiated. It can be used to do final initialization once these pieces are in place, such as retrieving views or restoring state.

The exact reasons why the rebuild order is not linear, I cannot tell you. It is probably more efficient to allow each component to re-start at its own pace rather than forcing a rigid order. For instance, I prefer that my LoaderManager starts as early as possible and we'll worry about the layout for it's content later.

(I love a good diagram.)

enter image description here

Sam
  • 86,580
  • 20
  • 181
  • 179
  • It is safe to init Loders in onActivityCreated() due to bug, not earlier. https://code.google.com/p/android/issues/detail?id=183783 – AppiDevo Mar 15 '17 at 08:59
  • Wow. I never knew that fragment is passed with activity instance as `context` through `onAttach()` while activity's `onCreate()` may yet to be called or finished! Helped me understand several weird issues in my app. – rpattabi Jan 24 '18 at 07:19
32

Fragments are restored during the Activity's onCreate(). Importantly though, they are restored in the base Activity class's onCreate(). Thus if you call super.onCreate() first, all of the rest of your onCreate() method will execute after your Fragments have been restored.

One possible solution then is to restore your state or calculate what ever data it is your Fragment's will need BEFORE you call super.onCreate()

The life cycle looks like this:

ACTIVITY onCreate (pre-super)
FRAGMENT onAttach
ACTIVITY onCreate (post-super)

So do something like this:

@Override
public void onCreate( final Bundle savedInstanceState )
{
    Log.d( TAG, "ACTIVITY onCreate (pre-super)" );
    // Do your processing here
    super.onCreate( savedInstanceState ); // Fragments will be restored here
    Log.d( TAG, "ACTIVITY onCreate (post-super)" );
}
Adam
  • 25,966
  • 23
  • 76
  • 87
  • 5
    I cant thank you enough for this answer. was searching 2 whole days for an answer to such a problem – user3213851 Jul 28 '15 at 19:24
  • 2
    It's worth mentioning that you can turn on "Don't Keep Activities" in developer settings to trigger this behavior without configuration changes. – cascal Jan 09 '17 at 19:32