Fragments are funny things but, so I thought, once you know their quirks they're an invaluable tool for writing good code across multiple devices.
However, while fixing an orientation change bug I've run up against a wall. For my fragment to work it needs access to a View which belongs to it's containing Activity leading me on a merry chase trying to find how the Activity & Fragment lifecycles interact.
I'm adding a fragment to my Activities view in it's onCreate()
method:
// Only add a fragment once, as after it's been added it cannot be replaced (Even though there is a .replace() method. Which is a massive gaping hole in fragments as a technology if you ask me)
if(savedInstanceState == null) {
MainMenuFragment menu= new MainMenuFragment();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.menuFrame, menu);
transaction.commit();
}
Leading to this Activity->Fragment Lifecycle:
01-04 15:17:27.226: W/SinglePaneActivity 0: onCreate()
01-04 15:17:27.378: W/MainMenuFragment 0: onAttach() to SinglePaneActivity 0
01-04 15:17:27.378: W/MainMenuFragment 0: onCreate()
01-04 15:17:27.453: W/MainMenuFragment 0: onActivityCreated()
01-04 15:17:27.476: W/MainMenuFragment 0: onStart()
01-04 15:17:27.476: W/SinglePaneActivity 0: onStart()
01-04 15:17:27.476: W/SinglePaneActivity 0: onResume()
01-04 15:17:27.476: W/MainMenuFragment 0: onResume()
An orientation change however highlights that this isn't usually the case, A fragments onCreate()
method isn't called after it's parent Activities onCreate()
. Infact, the first lifecycle call of a Fragment's onAttach()
occurs before the Activity has even been created (null
is passed as an argument):
01-04 15:10:49.589: W/MainMenuFragment 0: onPause()
01-04 15:10:49.589: W/SinglePaneActivity 0: onPause()
01-04 15:10:49.589: W/MainMenuFragment 0: onStop()
01-04 15:10:49.589: W/SinglePaneActivity 0: onStop()
01-04 15:10:49.589: W/MainMenuFragment 0: onDestroyView()
01-04 15:10:49.589: W/MainMenuFragment 0: onDestroy()
01-04 15:10:49.589: W/MainMenuFragment 0: onDetach()
01-04 15:10:49.609: W/SinglePaneActivity 0: onDestroy()
01-04 15:10:49.617: W/MainMenuFragment 1: onAttach() to null
01-04 15:10:49.617: W/MainMenuFragment 1: onCreate()
01-04 15:10:49.617: W/SinglePaneActivity 1: onCreate()
01-04 15:10:49.890: W/MainMenuFragment 1: onActivityCreated()
01-04 15:10:49.917: W/MainMenuFragment 1: onStart()
01-04 15:10:49.917: W/SinglePaneActivity 1: onStart()
01-04 15:10:49.921: W/SinglePaneActivity 1: onResume()
01-04 15:10:49.921: W/MainMenuFragment 1: onResume()
I have absolutely no idea why this is occuring. Could anyone shed any light on why Fragment.onAttach()
is being called before it's containing Activity has been created?
Fragments I've got which don't need access to their containing activity (until UI interaction) work as expected.
The fragment is not destroyed nor created after the rotation because the same fragment instance is used after the activity is recreated.
Activity is an application component that gives a user interface where the user can interact. The fragment is only part of an activity, it basically contributes its UI to that activity. Fragment is dependent on activity. It can't exist independently.
onCreate(Bundle) called to do initial creation of the fragment. onCreateView(LayoutInflater, ViewGroup, Bundle) creates and returns the view hierarchy associated with the fragment. onActivityCreated(Bundle) tells the fragment that its activity has completed its own Activity.
Activity is the part where the user will interacts with your application. In other words, it is responsible for creating a window to hold your UI components. (UI components and how to build a layout will be discussed in another article). Fragment represents a behavior or a portion of user interface in an Activity.
Argh,
01-04 15:46:23.175: W/MainMenuFragment 0: onAttach() to SinglePaneActivity 0
01-04 15:46:23.179: W/MainMenuFragment 0: onCreate()
01-04 15:46:23.246: W/MainMenuFragment 0: onActivityCreated() with Activity SinglePaneActivity 0
01-04 15:46:23.269: W/MainMenuFragment 0: onStart()
01-04 15:46:23.269: W/SinglePaneActivity 0: onStart()
Why the heck there is an onAttach()
method I have no idea. Especially since "attach" happens before there is an Activity.
The method I needed was of course, onActivityCreated()
which happens as the final call in the "Creation" set of Fragment lifecycle events.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With