Android apps need to handle changes in device configuration that can happen at run time, for example, screen orientation change, keyboard show or hide, or a change in language setting.
Standard Android behavior is:
- to destroy and recreate the running activity when the device configuration changes
- for activities and fragments to save their state in the OnSaveInstanceState method
- to restore states in the OnCreate or OnRestoreInstanceState method.
Learn more about handling configuration change in Android apps.
However, it is not possible to save and restore complex map data objects (for example maps, scenes, and layers) in this way. This is because large objects do not support the IParcelable interface, which is required for such objects to be added to a bundle.
This topic describes three options for dealing with configuration change in your app. Each option has different benefits and drawbacks, and may be appropriate in different parts of different apps. It is up to you, the developer, to choose the most appropriate option or options for your app. You may find the best approach is to use a combination of these options, as demonstrated in the options below.
Option 1: Retain fragment instance
Use Fragments to host the Views in your app, and call setRetainInstance on the Fragment object or objects that display map data. This prevents the Fragment from being destroyed when the Activity that contains it is destroyed and recreated. The Fragment must recreate the MapView/SceneView it uses to display the Map/Scene, because the old MapView/SceneView is associated with the old Activity that is destroyed. At this point, you can populate the new MapView/SceneView with an Map/ Scene or a collection of Layer objects if they still remain in memory, so data will not need to be fetched from the server again. If the Map/Scene or Layer objects have already been destroyed, they will need to be recreated.
This is the recommended option if your app uses config-dependent layouts, strings, drawables, dimensions, and so on. It comes at the small cost of the screen going blank for a moment when the MapView/SceneView is recreated and redisplayed.
Option 2: Handle configuration changes yourself
Configure the Activity(ies) that display map data to handle configuration changes yourself, to prevent the system from destroying and recreating the Activity(ies) when orientation and keyboard configuration changes occur. Add the android:configChanges attribute to the appropriate Activity element or elements in the app's AndroidManifest.xml file. For example, the following snippet indicates the Activity will manually handle any changes of device orientation, screen size, keyboard type, or accessibility:
AndroidManifest.xml file entry to handle configuration changes manually in an activity
<activity android:name=".ActivityName" android:label="@string/app_name" android:configChanges="orientation|screenSize|keyboard|keyboardHidden" ... />
This option can offer a smooth user experience when the configuration changes, because the MapView/SceneView and any contained objects do not need to be recreated, so there is minimal disruption to what the user sees on the screen.
However, it comes at a significant cost if your app makes extensive use of config-dependent layouts, strings, drawables, dimensions, and so on, as you must add code to the OnConfigurationChanged method in your activities to make any required changes to your app when the configuration changes. This process is also likely to be error prone. See Handling The Change in the Android developer documentation for a description of how to handle config changes yourself.
Option 3: Recreate all objects
Create new mapping data objects each time your Activity(ies) are created or recreated. This is the most straightforward option to implement, but gives the worst user experience, as all these objects (maps, scenes, views, layers, etc.) must be entirely recreated. Any server data will have to be fetched each time the Activity is destroyed and recreated, which is time consuming and uses more network communications than may otherwise be necessary.
However, all apps should implement this as a fallback option for scenarios where the original objects will be lost. For example, in options 1 and 2, your Fragment and/or Activity may be destroyed by the system if they are pushed into the background and memory resources become low. You'll need to recreate all your objects when your Activity is restarted.