| Scott Main | f940a1f | 2010-02-09 18:48:27 -0800 | [diff] [blame] | 1 | page.title=Handling Runtime Changes |
| Scott Main | 64461bf | 2013-04-11 19:32:08 -0700 | [diff] [blame] | 2 | page.tags="activity","lifecycle" |
| Scott Main | f940a1f | 2010-02-09 18:48:27 -0800 | [diff] [blame] | 3 | @jd:body |
| 4 | |
| 5 | <div id="qv-wrapper"> |
| 6 | <div id="qv"> |
| 7 | |
| 8 | <h2>In this document</h2> |
| 9 | <ol> |
| Scott Main | c6cb8a7 | 2010-04-09 15:52:18 -0700 | [diff] [blame] | 10 | <li><a href="#RetainingAnObject">Retaining an Object During a Configuration Change</a></li> |
| Scott Main | f940a1f | 2010-02-09 18:48:27 -0800 | [diff] [blame] | 11 | <li><a href="#HandlingTheChange">Handling the Configuration Change Yourself</a> |
| 12 | </ol> |
| 13 | |
| 14 | <h2>See also</h2> |
| 15 | <ol> |
| 16 | <li><a href="providing-resources.html">Providing Resources</a></li> |
| 17 | <li><a href="accessing-resources.html">Accessing Resources</a></li> |
| Scott Main | f284d49 | 2012-07-31 09:46:52 -0700 | [diff] [blame] | 18 | <li><a href="http://android-developers.blogspot.com/2009/02/faster-screen-orientation-change.html">Faster |
| 19 | Screen Orientation Change</a></li> |
| Scott Main | f940a1f | 2010-02-09 18:48:27 -0800 | [diff] [blame] | 20 | </ol> |
| 21 | </div> |
| 22 | </div> |
| 23 | |
| 24 | <p>Some device configurations can change during runtime |
| 25 | (such as screen orientation, keyboard availability, and language). When such a change occurs, |
| Scott Main | c6cb8a7 | 2010-04-09 15:52:18 -0700 | [diff] [blame] | 26 | Android restarts the running |
| Scott Main | 8da1191 | 2011-08-12 12:22:18 -0700 | [diff] [blame] | 27 | {@link android.app.Activity} ({@link android.app.Activity#onDestroy()} is called, followed by {@link |
| Scott Main | c6cb8a7 | 2010-04-09 15:52:18 -0700 | [diff] [blame] | 28 | android.app.Activity#onCreate(Bundle) onCreate()}). The restart behavior is designed to help your |
| 29 | application adapt to new configurations by automatically reloading your application with |
| Scott Main | 8da1191 | 2011-08-12 12:22:18 -0700 | [diff] [blame] | 30 | alternative resources that match the new device configuration.</p> |
| Scott Main | f940a1f | 2010-02-09 18:48:27 -0800 | [diff] [blame] | 31 | |
| Scott Main | 8da1191 | 2011-08-12 12:22:18 -0700 | [diff] [blame] | 32 | <p>To properly handle a restart, it is important that your activity restores its previous |
| Scott Main | 9bf45a0 | 2011-02-03 18:46:45 -0800 | [diff] [blame] | 33 | state through the normal <a |
| Scott Main | 50e990c | 2012-06-21 17:14:39 -0700 | [diff] [blame] | 34 | href="{@docRoot}guide/components/activities.html#Lifecycle">Activity |
| Scott Main | c6cb8a7 | 2010-04-09 15:52:18 -0700 | [diff] [blame] | 35 | lifecycle</a>, in which Android calls |
| 36 | {@link android.app.Activity#onSaveInstanceState(Bundle) onSaveInstanceState()} before it destroys |
| Scott Main | 8da1191 | 2011-08-12 12:22:18 -0700 | [diff] [blame] | 37 | your activity so that you can save data about the application state. You can then restore the state |
| Scott Main | c6cb8a7 | 2010-04-09 15:52:18 -0700 | [diff] [blame] | 38 | during {@link android.app.Activity#onCreate(Bundle) onCreate()} or {@link |
| Scott Main | 8da1191 | 2011-08-12 12:22:18 -0700 | [diff] [blame] | 39 | android.app.Activity#onRestoreInstanceState(Bundle) onRestoreInstanceState()}.</p> |
| Scott Main | c6cb8a7 | 2010-04-09 15:52:18 -0700 | [diff] [blame] | 40 | |
| Scott Main | 8da1191 | 2011-08-12 12:22:18 -0700 | [diff] [blame] | 41 | <p>To test that your application restarts itself with the application state intact, you should |
| 42 | invoke configuration changes (such as changing the screen orientation) while performing various |
| 43 | tasks in your application. Your application should be able to restart at any time without loss of |
| 44 | user data or state in order to handle events such as configuration changes or when the user receives |
| 45 | an incoming phone call and then returns to your application much later after your application |
| 46 | process may have been destroyed. To learn how you can restore your activity state, read about the <a |
| Scott Main | 50e990c | 2012-06-21 17:14:39 -0700 | [diff] [blame] | 47 | href="{@docRoot}guide/components/activities.html#Lifecycle">Activity lifecycle</a>.</p> |
| Scott Main | f940a1f | 2010-02-09 18:48:27 -0800 | [diff] [blame] | 48 | |
| 49 | <p>However, you might encounter a situation in which restarting your application and |
| Scott Main | c6cb8a7 | 2010-04-09 15:52:18 -0700 | [diff] [blame] | 50 | restoring significant amounts of data can be costly and create a poor user experience. In such a |
| Scott Main | 8da1191 | 2011-08-12 12:22:18 -0700 | [diff] [blame] | 51 | situation, you have two other options:</p> |
| Scott Main | f940a1f | 2010-02-09 18:48:27 -0800 | [diff] [blame] | 52 | |
| 53 | <ol type="a"> |
| Scott Main | 369c1c1 | 2010-12-07 11:17:00 -0800 | [diff] [blame] | 54 | <li><a href="#RetainingAnObject">Retain an object during a configuration change</a> |
| Scott Main | 8da1191 | 2011-08-12 12:22:18 -0700 | [diff] [blame] | 55 | <p>Allow your activity to restart when a configuration changes, but carry a stateful |
| 56 | {@link java.lang.Object} to the new instance of your activity.</p> |
| Scott Main | c6cb8a7 | 2010-04-09 15:52:18 -0700 | [diff] [blame] | 57 | |
| Scott Main | f940a1f | 2010-02-09 18:48:27 -0800 | [diff] [blame] | 58 | </li> |
| Scott Main | c6cb8a7 | 2010-04-09 15:52:18 -0700 | [diff] [blame] | 59 | <li><a href="#HandlingTheChange">Handle the configuration change yourself</a> |
| Scott Main | 8da1191 | 2011-08-12 12:22:18 -0700 | [diff] [blame] | 60 | <p>Prevent the system from restarting your activity during certain configuration |
| 61 | changes, but receive a callback when the configurations do change, so that you can manually update |
| 62 | your activity as necessary.</p> |
| Scott Main | f940a1f | 2010-02-09 18:48:27 -0800 | [diff] [blame] | 63 | </li> |
| 64 | </ol> |
| 65 | |
| Scott Main | f940a1f | 2010-02-09 18:48:27 -0800 | [diff] [blame] | 66 | |
| Scott Main | c6cb8a7 | 2010-04-09 15:52:18 -0700 | [diff] [blame] | 67 | <h2 id="RetainingAnObject">Retaining an Object During a Configuration Change</h2> |
| Scott Main | f940a1f | 2010-02-09 18:48:27 -0800 | [diff] [blame] | 68 | |
| Scott Main | 8da1191 | 2011-08-12 12:22:18 -0700 | [diff] [blame] | 69 | <p>If restarting your activity requires that you recover large sets of data, re-establish a network |
| 70 | connection, or perform other intensive operations, then a full restart due to a configuration change |
| 71 | might be a slow user experience. Also, it might not be possible for you to completely restore your |
| 72 | activity state with the {@link android.os.Bundle} that the system saves for you with the {@link |
| 73 | android.app.Activity#onSaveInstanceState(Bundle) onSaveInstanceState()} callback—it is not |
| 74 | designed to carry large objects (such as bitmaps) and the data within it must be serialized then |
| 75 | deserialized, which can consume a lot of memory and make the configuration change slow. In such a |
| 76 | situation, you can alleviate the burden of reinitializing your activity by retaining a stateful |
| 77 | {@link java.lang.Object} when your activity is restarted due to a configuration change.</p> |
| Scott Main | f940a1f | 2010-02-09 18:48:27 -0800 | [diff] [blame] | 78 | |
| Scott Main | 8da1191 | 2011-08-12 12:22:18 -0700 | [diff] [blame] | 79 | <p>To retain an object during a runtime configuration change:</p> |
| Scott Main | c6cb8a7 | 2010-04-09 15:52:18 -0700 | [diff] [blame] | 80 | <ol> |
| 81 | <li>Override the {@link android.app.Activity#onRetainNonConfigurationInstance()} method to return |
| Scott Main | 8da1191 | 2011-08-12 12:22:18 -0700 | [diff] [blame] | 82 | the object you would like to retain.</li> |
| 83 | <li>When your activity is created again, call {@link |
| 84 | android.app.Activity#getLastNonConfigurationInstance()} to recover your object.</li> |
| Scott Main | c6cb8a7 | 2010-04-09 15:52:18 -0700 | [diff] [blame] | 85 | </ol> |
| 86 | |
| Scott Main | 8da1191 | 2011-08-12 12:22:18 -0700 | [diff] [blame] | 87 | <p>When the Android system shuts down your activity due to a configuration change, it calls {@link |
| 88 | android.app.Activity#onRetainNonConfigurationInstance()} between the {@link |
| 89 | android.app.Activity#onStop()} and {@link android.app.Activity#onDestroy()} callbacks. In your |
| 90 | implementation of {@link android.app.Activity#onRetainNonConfigurationInstance()}, you can return |
| 91 | any {@link java.lang.Object} that you need in order to efficiently restore your state after the |
| 92 | configuration change.</p> |
| Scott Main | f940a1f | 2010-02-09 18:48:27 -0800 | [diff] [blame] | 93 | |
| 94 | <p>A scenario in which this can be valuable is if your application loads a lot of data from the |
| Scott Main | 8da1191 | 2011-08-12 12:22:18 -0700 | [diff] [blame] | 95 | web. If the user changes the orientation of the device and the activity restarts, your application |
| Scott Main | c6cb8a7 | 2010-04-09 15:52:18 -0700 | [diff] [blame] | 96 | must re-fetch the data, which could be slow. What you can do instead is implement |
| Scott Main | f940a1f | 2010-02-09 18:48:27 -0800 | [diff] [blame] | 97 | {@link android.app.Activity#onRetainNonConfigurationInstance()} to return an object carrying your |
| Scott Main | 8da1191 | 2011-08-12 12:22:18 -0700 | [diff] [blame] | 98 | data and then retrieve the data when your activity starts again with {@link |
| Scott Main | f940a1f | 2010-02-09 18:48:27 -0800 | [diff] [blame] | 99 | android.app.Activity#getLastNonConfigurationInstance()}. For example:</p> |
| 100 | |
| 101 | <pre> |
| 102 | @Override |
| 103 | public Object onRetainNonConfigurationInstance() { |
| 104 | final MyDataObject data = collectMyLoadedData(); |
| 105 | return data; |
| 106 | } |
| 107 | </pre> |
| 108 | |
| 109 | <p class="caution"><strong>Caution:</strong> While you can return any object, you |
| 110 | should never pass an object that is tied to the {@link android.app.Activity}, such as a {@link |
| 111 | android.graphics.drawable.Drawable}, an {@link android.widget.Adapter}, a {@link android.view.View} |
| 112 | or any other object that's associated with a {@link android.content.Context}. If you do, it will |
| Scott Main | 8da1191 | 2011-08-12 12:22:18 -0700 | [diff] [blame] | 113 | leak all the views and resources of the original activity instance. (Leaking resources |
| Scott Main | f940a1f | 2010-02-09 18:48:27 -0800 | [diff] [blame] | 114 | means that your application maintains a hold on them and they cannot be garbage-collected, so |
| 115 | lots of memory can be lost.)</p> |
| 116 | |
| Scott Main | 8da1191 | 2011-08-12 12:22:18 -0700 | [diff] [blame] | 117 | <p>Then retrieve the data when your activity starts again:</p> |
| Scott Main | f940a1f | 2010-02-09 18:48:27 -0800 | [diff] [blame] | 118 | |
| 119 | <pre> |
| 120 | @Override |
| 121 | public void onCreate(Bundle savedInstanceState) { |
| 122 | super.onCreate(savedInstanceState); |
| 123 | setContentView(R.layout.main); |
| 124 | |
| 125 | final MyDataObject data = (MyDataObject) getLastNonConfigurationInstance(); |
| 126 | if (data == null) { |
| 127 | data = loadMyData(); |
| 128 | } |
| 129 | ... |
| 130 | } |
| 131 | </pre> |
| 132 | |
| Scott Main | 8da1191 | 2011-08-12 12:22:18 -0700 | [diff] [blame] | 133 | <p>In this case, {@link android.app.Activity#getLastNonConfigurationInstance()} returns the data |
| 134 | saved by {@link android.app.Activity#onRetainNonConfigurationInstance()}. If {@code data} is null |
| 135 | (which happens when the activity starts due to any reason other than a configuration change) then |
| 136 | this code loads the data object from the original source.</p> |
| Scott Main | f940a1f | 2010-02-09 18:48:27 -0800 | [diff] [blame] | 137 | |
| 138 | |
| 139 | |
| 140 | |
| 141 | |
| 142 | <h2 id="HandlingTheChange">Handling the Configuration Change Yourself</h2> |
| 143 | |
| 144 | <p>If your application doesn't need to update resources during a specific configuration |
| 145 | change <em>and</em> you have a performance limitation that requires you to |
| Scott Main | 8da1191 | 2011-08-12 12:22:18 -0700 | [diff] [blame] | 146 | avoid the activity restart, then you can declare that your activity handles the configuration change |
| 147 | itself, which prevents the system from restarting your activity.</p> |
| Scott Main | f940a1f | 2010-02-09 18:48:27 -0800 | [diff] [blame] | 148 | |
| 149 | <p class="note"><strong>Note:</strong> Handling the configuration change yourself can make it much |
| Scott Main | c6cb8a7 | 2010-04-09 15:52:18 -0700 | [diff] [blame] | 150 | more difficult to use alternative resources, because the system does not automatically apply them |
| Scott Main | 8da1191 | 2011-08-12 12:22:18 -0700 | [diff] [blame] | 151 | for you. This technique should be considered a last resort when you must avoid restarts due to a |
| 152 | configuration change and is not recommended for most applications.</p> |
| Scott Main | f940a1f | 2010-02-09 18:48:27 -0800 | [diff] [blame] | 153 | |
| Scott Main | 8da1191 | 2011-08-12 12:22:18 -0700 | [diff] [blame] | 154 | <p>To declare that your activity handles a configuration change, edit the appropriate <a |
| 155 | href="{@docRoot}guide/topics/manifest/activity-element.html">{@code <activity>}</a> element in |
| 156 | your manifest file to include the <a |
| Scott Main | f940a1f | 2010-02-09 18:48:27 -0800 | [diff] [blame] | 157 | href="{@docRoot}guide/topics/manifest/activity-element.html#config">{@code |
| Scott Main | 8da1191 | 2011-08-12 12:22:18 -0700 | [diff] [blame] | 158 | android:configChanges}</a> attribute with a value that represents the configuration you want to |
| 159 | handle. Possible values are listed in the documentation for the <a |
| 160 | href="{@docRoot}guide/topics/manifest/activity-element.html#config">{@code |
| 161 | android:configChanges}</a> attribute (the most commonly used values are {@code "orientation"} to |
| 162 | prevent restarts when the screen orientation changes and {@code "keyboardHidden"} to prevent |
| 163 | restarts when the keyboard availability changes). You can declare multiple configuration values in |
| 164 | the attribute by separating them with a pipe {@code |} character.</p> |
| Scott Main | f940a1f | 2010-02-09 18:48:27 -0800 | [diff] [blame] | 165 | |
| Scott Main | 8da1191 | 2011-08-12 12:22:18 -0700 | [diff] [blame] | 166 | <p>For example, the following manifest code declares an activity that handles both the |
| Scott Main | f940a1f | 2010-02-09 18:48:27 -0800 | [diff] [blame] | 167 | screen orientation change and keyboard availability change:</p> |
| 168 | |
| 169 | <pre> |
| 170 | <activity android:name=".MyActivity" |
| 171 | android:configChanges="orientation|keyboardHidden" |
| 172 | android:label="@string/app_name"> |
| 173 | </pre> |
| 174 | |
| Scott Main | 8da1191 | 2011-08-12 12:22:18 -0700 | [diff] [blame] | 175 | <p>Now, when one of these configurations change, {@code MyActivity} does not restart. |
| 176 | Instead, the {@code MyActivity} receives a call to {@link |
| Scott Main | f940a1f | 2010-02-09 18:48:27 -0800 | [diff] [blame] | 177 | android.app.Activity#onConfigurationChanged(Configuration) onConfigurationChanged()}. This method |
| 178 | is passed a {@link android.content.res.Configuration} object that specifies |
| 179 | the new device configuration. By reading fields in the {@link android.content.res.Configuration}, |
| 180 | you can determine the new configuration and make appropriate changes by updating |
| 181 | the resources used in your interface. At the |
| Scott Main | 8da1191 | 2011-08-12 12:22:18 -0700 | [diff] [blame] | 182 | time this method is called, your activity's {@link android.content.res.Resources} object is updated |
| Scott Main | f940a1f | 2010-02-09 18:48:27 -0800 | [diff] [blame] | 183 | to return resources based on the new configuration, so you can easily |
| Scott Main | 8da1191 | 2011-08-12 12:22:18 -0700 | [diff] [blame] | 184 | reset elements of your UI without the system restarting your activity.</p> |
| 185 | |
| 186 | <p class="caution"><strong>Caution:</strong> Beginning with Android 3.2 (API level 13), <strong>the |
| 187 | "screen size" also changes</strong> when the device switches between portrait and landscape |
| 188 | orientation. Thus, if you want to prevent runtime restarts due to orientation change when developing |
| 189 | for API level 13 or higher (as declared by the <a |
| 190 | href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code minSdkVersion}</a> and <a |
| 191 | href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code targetSdkVersion}</a> |
| 192 | attributes), you must include the {@code "screenSize"} value in addition to the {@code |
| 193 | "orientation"} value. That is, you must decalare {@code |
| 194 | android:configChanges="orientation|screenSize"}. However, if your application targets API level |
| 195 | 12 or lower, then your activity always handles this configuration change itself (this configuration |
| 196 | change does not restart your activity, even when running on an Android 3.2 or higher device).</p> |
| Scott Main | f940a1f | 2010-02-09 18:48:27 -0800 | [diff] [blame] | 197 | |
| 198 | <p>For example, the following {@link |
| 199 | android.app.Activity#onConfigurationChanged(Configuration) onConfigurationChanged()} implementation |
| Scott Main | 8da1191 | 2011-08-12 12:22:18 -0700 | [diff] [blame] | 200 | checks the current device orientation:</p> |
| Scott Main | f940a1f | 2010-02-09 18:48:27 -0800 | [diff] [blame] | 201 | |
| 202 | <pre> |
| 203 | @Override |
| 204 | public void onConfigurationChanged(Configuration newConfig) { |
| 205 | super.onConfigurationChanged(newConfig); |
| 206 | |
| 207 | // Checks the orientation of the screen |
| 208 | if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) { |
| 209 | Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show(); |
| 210 | } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){ |
| 211 | Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show(); |
| 212 | } |
| Scott Main | f940a1f | 2010-02-09 18:48:27 -0800 | [diff] [blame] | 213 | } |
| 214 | </pre> |
| 215 | |
| 216 | <p>The {@link android.content.res.Configuration} object represents all of the current |
| 217 | configurations, not just the ones that have changed. Most of the time, you won't care exactly how |
| 218 | the configuration has changed and can simply re-assign all your resources that provide alternatives |
| 219 | to the configuration that you're handling. For example, because the {@link |
| 220 | android.content.res.Resources} object is now updated, you can reset |
| Scott Main | 8da1191 | 2011-08-12 12:22:18 -0700 | [diff] [blame] | 221 | any {@link android.widget.ImageView}s with {@link android.widget.ImageView#setImageResource(int) |
| 222 | setImageResource()} |
| Scott Main | f940a1f | 2010-02-09 18:48:27 -0800 | [diff] [blame] | 223 | and the appropriate resource for the new configuration is used (as described in <a |
| 224 | href="providing-resources.html#AlternateResources">Providing Resources</a>).</p> |
| 225 | |
| 226 | <p>Notice that the values from the {@link |
| 227 | android.content.res.Configuration} fields are integers that are matched to specific constants |
| 228 | from the {@link android.content.res.Configuration} class. For documentation about which constants |
| 229 | to use with each field, refer to the appropriate field in the {@link |
| 230 | android.content.res.Configuration} reference.</p> |
| 231 | |
| Scott Main | 8da1191 | 2011-08-12 12:22:18 -0700 | [diff] [blame] | 232 | <p class="note"><strong>Remember:</strong> When you declare your activity to handle a configuration |
| Scott Main | f940a1f | 2010-02-09 18:48:27 -0800 | [diff] [blame] | 233 | change, you are responsible for resetting any elements for which you provide alternatives. If you |
| Scott Main | 8da1191 | 2011-08-12 12:22:18 -0700 | [diff] [blame] | 234 | declare your activity to handle the orientation change and have images that should change |
| Scott Main | f940a1f | 2010-02-09 18:48:27 -0800 | [diff] [blame] | 235 | between landscape and portrait, you must re-assign each resource to each element during {@link |
| 236 | android.app.Activity#onConfigurationChanged(Configuration) onConfigurationChanged()}.</p> |
| 237 | |
| 238 | <p>If you don't need to update your application based on these configuration |
| 239 | changes, you can instead <em>not</em> implement {@link |
| 240 | android.app.Activity#onConfigurationChanged(Configuration) onConfigurationChanged()}. In |
| 241 | which case, all of the resources used before the configuration change are still used |
| Scott Main | 8da1191 | 2011-08-12 12:22:18 -0700 | [diff] [blame] | 242 | and you've only avoided the restart of your activity. However, your application should always be |
| 243 | able to shutdown and restart with its previous state intact, so you should not consider this |
| 244 | technique an escape from retaining your state during normal activity lifecycle. Not only because |
| 245 | there are other configuration changes that you cannot prevent from restarting your application, but |
| 246 | also because you should handle events such as when the user leaves your application and it gets |
| 247 | destroyed before the user returns to it.</p> |
| Scott Main | f940a1f | 2010-02-09 18:48:27 -0800 | [diff] [blame] | 248 | |
| Scott Main | 8da1191 | 2011-08-12 12:22:18 -0700 | [diff] [blame] | 249 | <p>For more about which configuration changes you can handle in your activity, see the <a |
| Scott Main | f940a1f | 2010-02-09 18:48:27 -0800 | [diff] [blame] | 250 | href="{@docRoot}guide/topics/manifest/activity-element.html#config">{@code |
| 251 | android:configChanges}</a> documentation and the {@link android.content.res.Configuration} |
| 252 | class.</p> |