Page 1 of 3
One of the things that you have to get used to when programming for a mobile platform is that your app can be shut down and restarted without much warning. This is something that often causes programmers from other platforms and beginners to make mistakes. You have to learn how to cope with this start-stop existence and that, for an Android app, it is a tough life just trying to stay alive.
Android Programming In Java:
Starting With an App
Is now available in paperback and ebook.
Available from Amazon.
- Getting Started With Android Studio 3
- The Activity And The UI
- Building The UI and a Calculator App
- Android Events
Extract: Using Lambdas
- Basic Controls
- Layout Containers
- The ConstraintLayout
Extract: Guidelines and Barriers
- UI Graphics A Deep Dive
Extract: Programming the UI ***NEW
- Menus & The Action Bar
- Menus, Context & Popup
- Beginning Bitmap Graphics
Extract: Simple Animation
- Staying Alive! Lifecycle & State
- ListView And Adapters
If you are interested in creating custom template also see:
Custom Projects In Android Studio
I recently encountered an Android app, created by a large well known company, that asked me to fill in a form. I was just about to press the Submit button when I accidental tilted the phone and the screen auto-rotated. When I looked again there was a blank form! I had to start over and being a programmer I couldn't resist testing to see if the data vanished from the form when I rotated the phone a second time - it did! The programmers are this big well known company had no idea about creating an Android app beyond the basics.
Don't fall into the same trap - find out about app lifetime, state and persisting data. It may sound like a boring topic but it is vital to the working of a UI.
Lifetime and State
Most programmers are used to the idea that their application will be started by the user, used and then terminated - by the user.
If the application is restarted then it is usually up to the user to load whatever context they need - documents etc. Sometimes an application has to automatically retain state information from run to run. For example, a game might keep track of where a user had got to - which level and score - but this is about as complicated as things get.
For an application running on a mobile device things are very different. The very nature of the device means that any application could be interrupted at any moment by an incoming phone call or the user making a phone call. To a certain extent this need to make app "interruptible" has been taken up by mobile phone operating systems as a more general principle. Android for example will stop your application running just because it needs the memory or wants to save battery life. It even terminates and restarts your application if a media reconfiguration is required.
For example, as we discovered in a previous chapter if the user changes the orientation of the device then your app is terminated and restarted. This is not quite a restart from scratch because the system saves and restores some state information automatically but exactly how all this works is something we have to find out.
The bottom line is that when you program under Android - and most other mobile operating systems - you have to care about the life cycle of your app and you have to take steps to ensure that its state is preserved so it can seem to the user that nothing at all has happened - even though you app has effectively been hit on the head and disposed of before being dragged back to continue from where it was.
Being an Android app is a dangerous existence and not at all like a Windows or a Linux app that lives a life of believe that they have the machine all to themselves.
The Life Cycle Of An App
The different states that an Android app can be in and the transitions between them can seem complicated at first - that's because they are.
If you are still thinking in terms of a desktop app that starts, runs and is terminated by the user this level of complexity can seem unnecessary - and perhaps it is. However these are the rules that we have to play by.
The Activity class has a set of overridable event handlers for each of the states. These work in pairs - bracketing the start and stop of the three types of Activity state.
At the outer most level there is
- onCreate and onDestroy - bracket the entire life of the Activity in memory.
This pair is called when the app is loaded into memory or unloaded from memory. These two bracket the entire lifetime of an Activity. When it is first loaded the onCreate is triggered and when the app is disposed of onDestroy is triggered. You clearly have to use these two to setup and destroy and resources which are needed for the entire lifetime of the app, However if your app is removed by the system it will call onDestroy just before unloading the Activity and onCreate when it reloads it. This means that onCreate may be called when you need to restore the state of the Activity so that the user doesn't notice any interruption.
- onStart and onStop - bracket any period that the app is visible.
It could be that the Activity is behind say a modal dialog box. The Activity is visible but not interacting with the user. This pair of events can be triggered multiple times during the entire lifetime of the app. Simple apps can mostly ignore the onStart and onStop events because the Activity is still in memory and doesn't loose any resources or state. The main use of onStart and onStop is to give the app an opportunity to monitor any changes that might affect it while not interacting with the user. To confuse the issue even more there is also on onRestart event which occurs before the onStart event but only if this isn't the first time the Activity has fired the onStart - that is this is a true restart.
- onResume and onPause - bracket the period that the Activity is in the foreground and interacting with the user.
Again this pair of events can happen multiple times during the entire lifetime. The onResume event occurs when the Activity returns to the foreground and doing its usual job. The onPause event occurs whent he user switches away to another app for example.
The Simple Approach
At this point you have every right to be confused.
So many changes of status and what to do at each one?
The main things to worry about is the complete restart of your app which triggers an onDestroy and an onCreate. This is the only one that destroys the current state of the app - the others are simply opportunities for your app to reduce the load on the system or to save some user data just in case.
As the onDestroy is usually just an opportunity to clean up resources to avoid leaks this means that most simple apps really only have to handle the onCreate event.
However, is tempting to think that this starting and stopping is just like a desktop app being terminated and then the user decides to use it again when it is fine fof the app to start off as if it was being run for the first time. In the case of an Android app this isn't what the user expects at all.
Your app can be terminated by the system without the user knowing anything about it. When the user tries to gain access to your app again they will generally expect it to carry on from where they left it.
It may be a complete restart as far as you are concerned but the user just switched to another app for a few minutes and expects to find yours as they left it.
What this means is that you cannot think about onCreate as if it was the constructor for your app. When onCreate is fired it might be the first time your program has ever run or it might be a restart and some things that you created on a previous start are still in existance. For simple applications you can often simply create everything again as if it was the first time your app had run - in some cases you need to test the savedInstanceState to see if you are actually just restarting.
Notice also that often these events also tend to occur in sequences.
For example an app that has just received the onPause event is likely to go on to receive the onDestroy event because the system will remove it to free up memory say. It is a mistake to try to think too much about sequences of events and ask which one should do any particular initialization or clean up.
Just think about the state that your app is moving into and place the necessary code into that event handler.