Wednesday, January 15, 2014

Android Activity/Fragment life cycle analysis

Android life cycle is complex when activity comes with fragments. Though the document improves a lot, it still has not covered all scenarios. To have a better understanding of it, I made a simple app to print out all critical life cycles for both activity and nested fragments.

First of all, it is important to point out that when all activities of an app are killed the app process may still be running. As long as the process is running, all static variables will be valid. Once the process is killed by the OS all static variables will be lost. So be careful to use static variables.

To cover all possible scenarios that may impact your android app, I categorised them below
  1. New created: Fragment/Activity starts from nothing
  2. Rotate new created: Fragment/Activity restarts after rotation
  3. Home key pressed: Fragment/Activity is kicked to the background
  4. Back from background
with the combination of different cases:
  1. Fragment sets RetainInstance true/false
  2. App is killed in the background after home key pressed. To simulate the app is killed by the system in the background, you can tick the box under Settings->Developer options->Don't keep activities. In this case, the active activity will be killed even the app is sent to background by pressing home button.

Here is the simple project used for the analysis
https://github.com/kejunxia/AndroidLifeCycleAnalysis

Also here is a library to apply Android MVC pattern and make the lifecycle easier to be used as well
http://kejunxia.github.io/AndroidMvc/
https://github.com/kejunxia/AndroidMvc

Summary:
  • New created: almost the same for the four scenarios as below. Except the sequence of onCreateView and onWindowFocusChanged
  • Rotate new created: When Fragment get set RetainInstance true, fragment doesn't call onCreate and onDestroy. And the following fragment calls are invoked but bundle passed in are null
    • onCreateView
    • onViewCreated
    • onActivityCreated
    • onViewStateRestored
    Also note that onSaveInstanceState for both Activity and Fragment is called with non-null outState, no matter if the fragment is set RetainInstance true or false. Which means activities and fragments always save instance state during rotation.
  • Home button pressed(send app to background): onSaveInstanceState is called with outState always as the result above. When fragment is set RetainInstance true, the following calls won't be called:
    • Activity.onDestroy
    • Fragment.onDestroyView
    • Fragment.onDestroy
    • Fragment.onDetach
    • Activity.onDetachedFromWindow
  •  Back from background: This is a little complicated. I split it in to 2 cases.
    • App killed by system: this is simulated by turning on Don't Keep Activities in developer settings on the device. In this case the system is going to try restoring the previous state which should be stored by onSaveInstanceState(as mentioned it's always called). This is different from creating a new activity. In this case the system will do the things below:
      • Activity.onCreate will be called with the savedInstanceState to recover previous state, while if it's creating a new activity onCreate will recieve a null bundle.
      • Fragment.onAttach
      • Activity.onAttachFragment
      • Activity.onStart NOTE THAT this will be called after the fragment is attached while if it's new creating activity, onstart is before the fragment is attached.
      • Fragment.onCreate will be called with savedInstanceState like the activity.
      • Activity.onRestoreInstanceState is called which won't be called when creating a new activity
    • Back from background before killed:
      • no creation will occur
      • no savedInstanceState will occur

Life cycle outputs:

========================================================================
Activity:                            new created
Fragment retainInstance:   false
Kill Activity immediately:   false
ActivityCycle﹕ onCreate: bundle=null
ActivityCycle﹕ onCreateView
          Called many times here
ActivityCycle﹕ onStart
FragmentCycle===>﹕ onAttach
ActivityCycle﹕ onAttachFragment
FragmentCycle===>﹕ onCreate: bundle=null
FragmentCycle===>﹕ onCreateView: bundle=null
ActivityCycle﹕ onCreateView
ActivityCycle﹕ onCreateView
ActivityCycle﹕ onCreateView
ActivityCycle﹕ onCreateView
FragmentCycle===>﹕ onViewCreated: bundle=null
FragmentCycle===>﹕ onActivityCreated: bundle=null
FragmentCycle===>﹕ onViewStateRestored: bundle=null
FragmentCycle===>﹕ onStart
ActivityCycle﹕ onPostCreate: bundle=null
ActivityCycle﹕ onResume
ActivityCycle﹕ onPostResume
ActivityCycle﹕ onResumeFragments`
FragmentCycle===>﹕ onResume
ActivityCycle﹕ onAttachedToWindow
ActivityCycle﹕ onWindowFocusChanged
ActivityCycle﹕ onCreateView
ActivityCycle﹕ onCreateView

Activity:                            rotate new created
Fragment retainInstance:   false
Kill Activity immediately:   false
ActivityCycle﹕ onPause
FragmentCycle===>﹕ onPause
ActivityCycle﹕ onSaveInstanceState: outState=Object
FragmentCycle===>﹕ onSaveInstanceState: outState=Object
ActivityCycle﹕ onStop
FragmentCycle===>﹕ onStop
ActivityCycle﹕ onDestroy
FragmentCycle===>﹕ onDestroyView
FragmentCycle===>﹕ onDestroy
FragmentCycle===>﹕ onDetach
ActivityCycle﹕ onDetachedFromWindow
ActivityCycle﹕ onCreate: bundle=Object
FragmentCycle===>﹕ onAttach
ActivityCycle﹕ onAttachFragment
FragmentCycle===>﹕ onCreate: bundle=Object
ActivityCycle﹕ onCreateView
          Called many times here
ActivityCycle﹕ onStart
FragmentCycle===>﹕ onCreateView: bundle=Object
ActivityCycle﹕ onCreateView
ActivityCycle﹕ onCreateView
ActivityCycle﹕ onCreateView
ActivityCycle﹕ onCreateView
FragmentCycle===>﹕ onViewCreated: bundle=Object
FragmentCycle===>﹕ onActivityCreated: bundle=Object
FragmentCycle===>﹕ onViewStateRestored: bundle=Object
FragmentCycle===>﹕ onStart
ActivityCycle﹕ onRestoreInstanceState: bundle=Object
ActivityCycle﹕ onPostCreate: bundle=Object
ActivityCycle﹕ onResume
ActivityCycle﹕ onPostResume
ActivityCycle﹕ onResumeFragments
FragmentCycle===>﹕ onResume
ActivityCycle﹕ onAttachedToWindow
ActivityCycle﹕ onCreateView
ActivityCycle﹕ onCreateView
ActivityCycle﹕ onWindowFocusChanged

Activity:                           home button pressed
Fragment retainInstance:   false
Kill Activity immediately:   false
ActivityCycle﹕ onPause
FragmentCycle===>﹕ onPause
ActivityCycle﹕ onWindowFocusChanged
ActivityCycle﹕ onSaveInstanceState: outState=Object
FragmentCycle===>﹕ onSaveInstanceState: outState=Object
ActivityCycle﹕ onStop
FragmentCycle===>﹕ onStop

Activity:                            back from background
Fragment retainInstance:   false
Kill Activity immediately:   false
ActivityCycle﹕ onRestart
ActivityCycle﹕ onStart
FragmentCycle===>﹕ onStart
ActivityCycle﹕ onResume
ActivityCycle﹕ onPostResume
ActivityCycle﹕ onResumeFragments
FragmentCycle===>﹕ onResume
ActivityCycle﹕ onWindowFocusChanged

========================================================================
Activity:                            new created
Fragment retainInstance:   true
Kill Activity immediately:   false

ActivityCycle﹕ onCreate: bundle=null
ActivityCycle﹕ onCreateView
          Called many times here
ActivityCycle﹕ onStart
FragmentCycle===>﹕ onAttach
ActivityCycle﹕ onAttachFragment
FragmentCycle===>﹕ onCreate: bundle=null
FragmentCycle===>﹕ onCreateView: bundle=null
ActivityCycle﹕ onCreateView
ActivityCycle﹕ onCreateView
ActivityCycle﹕ onCreateView
ActivityCycle﹕ onCreateView
FragmentCycle===>﹕ onViewCreated: bundle=null
FragmentCycle===>﹕ onActivityCreated: bundle=null
FragmentCycle===>﹕ onViewStateRestored: bundle=null
FragmentCycle===>﹕ onStart
ActivityCycle﹕ onPostCreate: bundle=null
ActivityCycle﹕ onResume
ActivityCycle﹕ onPostResume
ActivityCycle﹕ onResumeFragments
FragmentCycle===>﹕ onResume
ActivityCycle﹕ onAttachedToWindow
ActivityCycle﹕ onWindowFocusChanged
ActivityCycle﹕ onCreateView
ActivityCycle﹕ onCreateView

Activity:                            rotate new created
Fragment retainInstance:   true
Kill Activity immediately:   false
ActivityCycle﹕ onPause
FragmentCycle===>﹕ onPause
ActivityCycle﹕ onSaveInstanceState: outState=Object
FragmentCycle===>﹕ onSaveInstanceState: outState=Object
ActivityCycle﹕ onStop
FragmentCycle===>﹕ onStop
ActivityCycle﹕ onDestroy
FragmentCycle===>﹕ onDestroyView
FragmentCycle===>﹕ onDetach
ActivityCycle﹕ onDetachedFromWindow
ActivityCycle﹕ onCreate: bundle=Object
FragmentCycle===>﹕ onAttach
ActivityCycle﹕ onAttachFragment
ActivityCycle﹕ onCreateView
          Called many times here
ActivityCycle﹕ onStart
FragmentCycle===>﹕ onCreateView: bundle=null
ActivityCycle﹕ onCreateView
ActivityCycle﹕ onCreateView
ActivityCycle﹕ onCreateView
ActivityCycle﹕ onCreateView
FragmentCycle===>﹕ onViewCreated: bundle=null
FragmentCycle===>﹕ onActivityCreated: bundle=null
FragmentCycle===>﹕ onViewStateRestored: bundle=null
FragmentCycle===>﹕ onStart
ActivityCycle﹕ onRestoreInstanceState: bundle=Object
ActivityCycle﹕ onPostCreate: bundle=Object
ActivityCycle﹕ onResume
ActivityCycle﹕ onPostResume
ActivityCycle﹕ onResumeFragments
FragmentCycle===>﹕ onResume
ActivityCycle﹕ onAttachedToWindow
ActivityCycle﹕ onCreateView
ActivityCycle﹕ onCreateView
ActivityCycle﹕ onWindowFocusChanged

Activity:                            home button pressed
Fragment retainInstance:   true
Kill Activity immediately:   
false
ActivityCycle﹕ onPause
FragmentCycle===>﹕ onPause
ActivityCycle﹕ onWindowFocusChanged
ActivityCycle﹕ onSaveInstanceState: outState=Object
FragmentCycle===>﹕ onSaveInstanceState: outState=Object
ActivityCycle﹕ onStop
FragmentCycle===>﹕ onStop


Activity:                            back from background
Fragment retainInstance:   true
Kill Activity immediately:   
false
ActivityCycle﹕ onRestart
ActivityCycle﹕ onStart
FragmentCycle===>﹕ onStart
ActivityCycle﹕ onResume
ActivityCycle﹕ onPostResume
ActivityCycle﹕ onResumeFragments
FragmentCycle===>﹕ onResume
ActivityCycle﹕ onWindowFocusChanged

======================================================================
Activity:                            new created
Fragment retainInstance:   true
Kill Activity immediately:   true
ActivityCycle﹕ onCreate: bundle=null
ActivityCycle﹕ onCreateView
          Called many times here
ActivityCycle﹕ onStart
FragmentCycle===>﹕ onAttach
ActivityCycle﹕ onAttachFragment
FragmentCycle===>﹕ onCreate: bundle=null
FragmentCycle===>﹕ onCreateView: bundle=null
ActivityCycle﹕ onCreateView
ActivityCycle﹕ onCreateView
ActivityCycle﹕ onCreateView
ActivityCycle﹕ onCreateView
FragmentCycle===>﹕ onViewCreated: bundle=null
FragmentCycle===>﹕ onActivityCreated: bundle=null
FragmentCycle===>﹕ onViewStateRestored: bundle=null
FragmentCycle===>﹕ onStart
ActivityCycle﹕ onPostCreate: bundle=null
ActivityCycle﹕ onResume
ActivityCycle﹕ onPostResume
ActivityCycle﹕ onResumeFragments
FragmentCycle===>﹕ onResume
ActivityCycle﹕ onAttachedToWindow
ActivityCycle﹕ onWindowFocusChanged
ActivityCycle﹕ onCreateView
ActivityCycle﹕ onCreateView


Activity:                            rotate new created
Fragment retainInstance:   true
Kill Activity immediately:   true
ActivityCycle﹕ onPause
FragmentCycle===>﹕ onPause
ActivityCycle﹕ onSaveInstanceState: outState=Object
FragmentCycle===>﹕ onSaveInstanceState: outState=Object
ActivityCycle﹕ onStop
FragmentCycle===>﹕ onStop
ActivityCycle﹕ onDestroy
FragmentCycle===>﹕ onDestroyView
FragmentCycle===>﹕ onDetach
ActivityCycle﹕ onDetachedFromWindow
ActivityCycle﹕ onCreate: bundle=Object
FragmentCycle===>﹕ onAttach
ActivityCycle﹕ onAttachFragment
ActivityCycle﹕ onCreateView
          Called many times here
ActivityCycle﹕ onStart
FragmentCycle===>﹕ onCreateView: bundle=null
ActivityCycle﹕ onCreateView
ActivityCycle﹕ onCreateView
ActivityCycle﹕ onCreateView
ActivityCycle﹕ onCreateView
FragmentCycle===>﹕ onViewCreated: bundle=null
FragmentCycle===>﹕ onActivityCreated: bundle=null
FragmentCycle===>﹕ onViewStateRestored: bundle=null
FragmentCycle===>﹕ onStart
ActivityCycle﹕ onRestoreInstanceState: bundle=Object
ActivityCycle﹕ onPostCreate: bundle=Object
ActivityCycle﹕ onResume
ActivityCycle﹕ onPostResume
ActivityCycle﹕ onResumeFragments
FragmentCycle===>﹕ onResume
ActivityCycle﹕ onAttachedToWindow
ActivityCycle﹕ onCreateView
ActivityCycle﹕ onCreateView
ActivityCycle﹕ onWindowFocusChanged


Activity:                            home button pressed
Fragment retainInstance:   true
Kill Activity immediately:   true
ActivityCycle﹕ onPause
FragmentCycle===>﹕ onPause
ActivityCycle﹕ onWindowFocusChanged
ActivityCycle﹕ onSaveInstanceState: outState=Object
FragmentCycle===>﹕ onSaveInstanceState: outState=Object
ActivityCycle﹕ onStop
FragmentCycle===>﹕ onStop
ActivityCycle﹕ onDestroy
FragmentCycle===>﹕ onDestroyView
FragmentCycle===>﹕ onDestroy
FragmentCycle===>﹕ onDetach
ActivityCycle﹕ onDetachedFromWindow


Activity:                            back from background
Fragment retainInstance:   true
Kill Activity immediately:   true
ActivityCycle﹕ onCreate: bundle=Object
FragmentCycle===>﹕ onAttach
ActivityCycle﹕ onAttachFragment
FragmentCycle===>﹕ onCreate: bundle=Object
ActivityCycle﹕ onCreateView
          Called many times here
ActivityCycle﹕ onStart
FragmentCycle===>﹕ onCreateView: bundle=Object
ActivityCycle﹕ onCreateView
ActivityCycle﹕ onCreateView
ActivityCycle﹕ onCreateView
ActivityCycle﹕ onCreateView
FragmentCycle===>﹕ onViewCreated: bundle=Object
FragmentCycle===>﹕ onActivityCreated: bundle=Object
FragmentCycle===>﹕ onViewStateRestored: bundle=Object
FragmentCycle===>﹕ onStart
ActivityCycle﹕ onRestoreInstanceState: bundle=Object
ActivityCycle﹕ onPostCreate: bundle=Object
ActivityCycle﹕ onResume
ActivityCycle﹕ onPostResume
ActivityCycle﹕ onResumeFragments
FragmentCycle===>﹕ onResume
ActivityCycle﹕ onAttachedToWindow
ActivityCycle﹕ onCreateView
ActivityCycle﹕ onCreateView
ActivityCycle﹕ onWindowFocusChanged


======================================================================
Activity:                            new created
Fragment retainInstance:   false
Kill Activity immediately:   true
ActivityCycle﹕ onCreate: bundle=null
ActivityCycle﹕ onCreateView
          Called many times here
ActivityCycle﹕ onStart
FragmentCycle===>﹕ onAttach
ActivityCycle﹕ onAttachFragment
FragmentCycle===>﹕ onCreate: bundle=null
FragmentCycle===>﹕ onCreateView: bundle=null
ActivityCycle﹕ onCreateView
ActivityCycle﹕ onCreateView
ActivityCycle﹕ onCreateView
ActivityCycle﹕ onCreateView
FragmentCycle===>﹕ onViewCreated: bundle=null
FragmentCycle===>﹕ onActivityCreated: bundle=null
FragmentCycle===>﹕ onViewStateRestored: bundle=null
FragmentCycle===>﹕ onStart
ActivityCycle﹕ onPostCreate: bundle=null
ActivityCycle﹕ onResume
ActivityCycle﹕ onPostResume
ActivityCycle﹕ onResumeFragments
FragmentCycle===>﹕ onResume
ActivityCycle﹕ onAttachedToWindow
ActivityCycle﹕ onCreateView
ActivityCycle﹕ onCreateView
ActivityCycle﹕ onWindowFocusChanged


Activity:                            rotate new created
Fragment retainInstance:   false
Kill Activity immediately:   true
ActivityCycle﹕ onPause
FragmentCycle===>﹕ onPause
ActivityCycle﹕ onSaveInstanceState: outState=Object
FragmentCycle===>﹕ onSaveInstanceState: outState=Object
ActivityCycle﹕ onStop
FragmentCycle===>﹕ onStop
ActivityCycle﹕ onDestroy
FragmentCycle===>﹕ onDestroyView
FragmentCycle===>﹕ onDestroy
FragmentCycle===>﹕ onDetach
ActivityCycle﹕ onDetachedFromWindow
ActivityCycle﹕ onCreate: bundle=Object
FragmentCycle===>﹕ onAttach
ActivityCycle﹕ onAttachFragment
FragmentCycle===>﹕ onCreate: bundle=Object
ActivityCycle﹕ onCreateView
          Called many times here
ActivityCycle﹕ onStart
FragmentCycle===>﹕ onCreateView: bundle=Object
ActivityCycle﹕ onCreateView
ActivityCycle﹕ onCreateView
ActivityCycle﹕ onCreateView
ActivityCycle﹕ onCreateView
FragmentCycle===>﹕ onViewCreated: bundle=Object
FragmentCycle===>﹕ onActivityCreated: bundle=Object
FragmentCycle===>﹕ onViewStateRestored: bundle=Object
FragmentCycle===>﹕ onStart
ActivityCycle﹕ onRestoreInstanceState: bundle=Object
ActivityCycle﹕ onPostCreate: bundle=Object
ActivityCycle﹕ onResume
ActivityCycle﹕ onPostResume
ActivityCycle﹕ onResumeFragments
FragmentCycle===>﹕ onResume
ActivityCycle﹕ onAttachedToWindow
ActivityCycle﹕ onCreateView
ActivityCycle﹕ onCreateView
ActivityCycle﹕ onWindowFocusChanged

Activity:                            home button pressed
Fragment retainInstance:   false
Kill Activity immediately:   true
ActivityCycle﹕ onPause
FragmentCycle===>﹕ onPause
ActivityCycle﹕ onWindowFocusChanged
ActivityCycle﹕ onSaveInstanceState: outState=Object
FragmentCycle===>﹕ onSaveInstanceState: outState=Object
ActivityCycle﹕ onStop
FragmentCycle===>﹕ onStop
ActivityCycle﹕ onDestroy
FragmentCycle===>﹕ onDestroyView
FragmentCycle===>﹕ onDestroy
FragmentCycle===>﹕ onDetach
ActivityCycle﹕ onDetachedFromWindow

Activity:                            back from background
Fragment retainInstance:   false
Kill Activity immediately:   true
ActivityCycle﹕ onCreate: bundle=Object
FragmentCycle===>﹕ onAttach
ActivityCycle﹕ onAttachFragment
FragmentCycle===>﹕ onCreate: bundle=Object
ActivityCycle﹕ onCreateView          Called many times here
ActivityCycle﹕ onStart
FragmentCycle===>﹕ onCreateView: bundle=Object
ActivityCycle﹕ onCreateView
ActivityCycle﹕ onCreateView
ActivityCycle﹕ onCreateView
ActivityCycle﹕ onCreateView
FragmentCycle===>﹕ onViewCreated: bundle=Object
FragmentCycle===>﹕ onActivityCreated: bundle=Object
FragmentCycle===>﹕ onViewStateRestored: bundle=Object
FragmentCycle===>﹕ onStart
ActivityCycle﹕ onRestoreInstanceState: bundle=Object
ActivityCycle﹕ onPostCreate: bundle=Object
ActivityCycle﹕ onResume
ActivityCycle﹕ onPostResume
ActivityCycle﹕ onResumeFragments
FragmentCycle===>﹕ onResume
ActivityCycle﹕ onAttachedToWindow
ActivityCycle﹕ onCreateView
ActivityCycle﹕ onCreateView
ActivityCycle﹕ onWindowFocusChanged

19 comments:

  1. I think you can ignore the onCreateView calls. They don't have much to do with lifecycle. Those calls are factory invokations when the framework is inflating each view from the xml (hence multiple calls).

    ReplyDelete
  2. Useful blog to Android Activity/Fragment life cycle analysisAndroid Training

    ReplyDelete
  3. It is really a great work and the way in which u r sharing the knowledge is excellent.
    Thanks for helping me to understand basic concepts. As a beginner in android programming your post help me a lot.Thanks for your informative article. Android Training in velachery | Android Training institute in chennai

    ReplyDelete
  4. It is really a great work and the way in which u r sharing the knowledge is excellent.
    Thanks for helping me to understand basic concepts. As a beginner in android programming your post help me a lot.Thanks for your informative article. Android Training in velachery | Android Training institute in chennai

    ReplyDelete
  5. Your blog has given me that thing which I never expect to get from all over the websites. Nice post guys!

    Melbourne SEO Services

    ReplyDelete
  6. Its a wonderful post and very helpful, thanks for all this information. You are including better information regarding this topic in an effective way.Thank you so much

    Personal Installment Loans
    Payday Cash Advance loan
    Title Car loan
    Cash Advance Loan

    ReplyDelete

  7. Its a wonderful post and very helpful, thanks for all this information. You are including better information regarding this topic in an effective way.Thank you so much

    Installment Loans Near Me
    Title loans Near Me
    Cash Advances Near Me

    ReplyDelete
  8. I read this article. I think You put a lot of effort to create this article. I appreciate your work.
    thesis Writing Service

    ReplyDelete
  9. I am really happy with your blog because your article is very unique and powerful for new reader.
    selenium training in chennai
    selenium training in bangalore

    ReplyDelete
  10. Hello. This post couldn’t be written any better! Reading this post reminds me of my previous roommate. He always kept chatting about this. I will forward this page to him. Fairly certain he will have a good read. Thank you for sharing.
    AWS Training in Bangalore |Best AWS Training Institute in Bangalore BTM, Marathahalli
    AWS Training in Chennai | AWS Training Institute in Chennai Velachery, Tambaram, OMR

    ReplyDelete
  11. This comment has been removed by the author.

    ReplyDelete
  12. Well Said, you have furnished the right information that will be useful to anyone at all time. Thanks for sharing your Ideas.

    angularjs Training in chennai
    angularjs Training in chennai

    angularjs-Training in tambaram

    angularjs-Training in sholinganallur

    ReplyDelete
  13. Really nice experience you have. Thank you for sharing. It will surely be an experience to someone.
    Python training in marathahalli | Python training institute in pune

    ReplyDelete
  14. This comment has been removed by the author.

    ReplyDelete
  15. Your good knowledge and kindness in playing with all the pieces were very useful. I don’t know what I would have done if I had not encountered such a step like this.
    advanced excel training in bangalore

    ReplyDelete
  16. Wow it is really wonderful and awesome thus it is very much useful for me to understand many concepts and helped me a lot. it is really explainable very well and i got more information from your blog.

    blueprism training in chennai | blueprism training in bangalore | blueprism training in pune | blueprism online training

    ReplyDelete
  17. This is beyond doubt a blog significant to follow. You’ve dig up a great deal to say about this topic, and so much awareness. I believe that you recognize how to construct people pay attention to what you have to pronounce, particularly with a concern that’s so vital. I am pleased to suggest this blog.
    Java training in Jaya nagar | Java training in Electronic city

    Java training in Chennai | Java training in USA | Java training in Kalyan nagar

    ReplyDelete
  18. I found this informative and interesting blog so i think so its very useful and knowledge able.I would like to thank you for the efforts you have made in writing this article.

    Data Science training in Chennai | Data science training in bangalore

    Data science training in pune | Data science online training

    Data Science Interview questions and answers

    ReplyDelete