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