Android Programming In Kotlin: State Management
Written by Mike James   
Monday, 11 March 2019
Article Index
Android Programming In Kotlin: State Management
Complex UI Elements

Android apps can be stopped and restarted at any time. Managing an app's state is a big problem unless you master the bundle and more. Here's how to do it in Kotlin, in an extract from my published book Android Programming in Kotlin: Starting With An App.

Android Programming In Kotlin
Starting with an App

Covers Android Studio 3 and Constraint Layout.

Is now available as a print book:

coverKotlinsmall

Buy from: Amazon

Contents

  1. Getting Started With Android Studio 3
  2. The Activity And The UI
  3. Building The UI and a Calculator App
  4. Android Events
  5. Basic Controls
  6. Layout Containers
  7. The ConstraintLayout 
    Extract Bias & Chains 
  8. Programming The UI
    Extract Programming the UI
    Extract Layouts and Autonaming Components
  9. Menus & The Action Bar
  10. Menus, Context & Popup
  11. Resources
    Extract Conditional Resources
  12. Beginning Bitmap Graphics
    Extract Animation
  13. Staying Alive! Lifecycle & State
    Extract  State Managment ***NEW!
  14. Spinners
  15. Pickers
  16. ListView And Adapters
  17. Android The Kotlin Way

If you are interested in creating custom template also see:

Custom Projects In Android Studio

Androidgears

 

Retaining State – the Bundle

When you change orientation your app is stopped and restarted. When this happens for example a TextView is reset to its default state when the app loads. This description of what is happening is perhaps what you might expect. However, this isn't the complete story.

The system does try to help you with the problem of having your app stopped in its tracks and restarted. It will automatically retain the state of UI elements that can be modified by the user, and it automatically restores them when the app starts.

So in principle you can initially ignore the problem of an app restart because the system restores your UI. This is the reason that some Android programmers assume that everything is "normal" and there is no need to study the lifecycle of an app. This is true at first, but later your app will evolve beyond what the system provides by default.

Automatically saving and restoring the UI's state is what the savedInstanceState parameter in the onCreate event handler is all about:

override fun onCreate(savedInstanceState: Bundle?) {

A Bundle is a set of key/value pairs which is used to save the values stored in UI elements when the app is stopped by the system. It stores id/value pairs and when the app is restarted the Bundle is used to initialize the values in the corresponding UI elements. Notice that if the user stops your app by removing it from the recent apps list then the savedInstanceState is destroyed, the app really does start over afresh, and the onCreate isn't passed a Bundle to restore the UI. In other words, savedInstanceState only restores the UI when the app has been stopped by the system. 

It is also worth noticing that the restore will work to an alternative layout loaded because of a configuration change. For example, it will restore state to a landscape version of a layout as well as the original portrait version. All that matters is that the current layout has View objects with the correct ids.

At this point you are probably wondering why a modified TextView object isn't restored by the system when the device isrotated? The simple answer is that a TextView object isn't intended for user interaction – it is supposed to just be used to show static text labels and so the system doesn't save and restore it. 

  • The general principle is that any UI element that can be modified by the user is automatically saved and restored. Any changes that your code makes or that the user makes in complex UI components are lost unless you take steps to preserve them.

Saving Additional UI Data

The system will save and restore the state of the UI elements that the user can change, but it will not store any that your code changes. It also doesn't automatically save and restore any other data that the user or your code may have generated that isn't within the UI. In these cases you have to write some code that saves the values and restores them. 

There are lots of ways of saving the state of an app as it is started and stopped by the system. One of the simplest is to use the Bundle object that the system uses. 

The system fires the onSaveInstanceState event when it is about to add data to the Bundle and save it. If you want to save some additional data all you have to do is override the default event handler. For example, suppose you want to save and restore the data in the TextView in the Lifecycle Explorer (complete code in book). First you have to save the data:

override fun onSaveInstanceState(outState: Bundle?) {
	super.onSaveInstanceState(outState)
	outState?.putCharSequence("myText",textView.text)
}

Notice that we save the text content of the textView object as the value and use the key "myText". In most cases it would be better to create a string constant for the key. The key can be any identifier you care to use, but it has to be unique within the Bundle as it is used to retrieve the data you have stored in the Bundle. 

Now to retrieve the data and place it into the TextView we need to change the onCreate event handler:

override fun onCreate(savedInstanceState: Bundle?) {
	super.onCreate(savedInstanceState)
	setContentView(R.layout.activity_main)
	setSupportActionBar(toolbar)
	textView.append("Create\n")
	if (savedInstanceState != null){
	 textView.text=
savedInstanceState.getCharSequence("myText") }

This starts off in the usual way but now we check to see if savedInstanceState has any data. If it does we retrieve the stored text using the key "myText". 

<ASIN:1871962544>

<ASIN:1871962536>



Last Updated ( Wednesday, 13 March 2019 )