Sometimes handling the orientation changes for your Activity, Fragment or AsyncTasks becomes most frustrating things to deal. If orientation changes is not handle properly then it results unexpected behavior of the application.
When such changes occurs, Android restarts the running Activity means it destroy and again created.
When configurations changed during run time (such as screen orientation, keyboard availability, and language), Android usually destroys application’s existing Activity or Fragment and recreate it.
Android does this so that application can reload its resources based on the new configuration. The restart behavior helps application to adapt new configurations by automatically reloading the application with alternative resources that match the new device configuration.
Proper handling of orientation changes makes rich user experience (not lost UI state) for the application and it also avoiding memory leaks.
How to handle?
To handle these configuration changes, Android provides callbacks to save your application state before destroying either Activity or Fragment. In the same it also provides to restore the application state when it is recreating them.
There are a different options to handle the orientation changes:
1. Lock screen orientation
2. Prevent Activity to recreated
3. Save basic state
4. Save complex objects
Lock screen orientation
To lock the screen orientation change of any screen (activity) of your android application makes your activity display only in one mode i.e. either Landscape or Portrait. This is the simplest way to handle screen orientation but not generally recommended.
For this you need to add below line in your projects AndroidManifest.xml. Add the below line along with your activity entry in the AndroidManifest file.
Prevent Activity to recreated
Another most common solution to dealing with orientation changes by setting the android:configChanges flag on your Activity in AndroidManifest.xml. Using this attribute your Activities won’t be recreated and all your views and data will still be there after orientation change.
This attribute informs to Android system that you are going to handle orientation and screenSize changes for this Activity. So instead of destroying and recreating your Activity, Android will just rotate the screen and invoke one of the lifecycle callback method which is onConfigurationChanged(Configuration).
Note: In case you want to do something like display different layout then you have to implement onConfigurationChanged(Configuration) method and before inflating the new layout, you would require to manually discard the old layout. To use android:configChanges attribute is also not recommended by Android.
Save basic state
This is the most common situation to save the basic data of your Activity or Fragment during orientation change. You can save Primitive data such as String, Boolean, Integers or Parcelable objects in a Bundle during the orientation change and read the same data when Activity recreated.
Saving and restoring the data works using two Activity lifecycle methods called onSaveInstanceState() and onRestoreInstanceState().
To save the state information override onSaveInstanceState() method and add key-value pairs to the Bundle object that is saved in the event that your activity is destroyed unexpectedly. This method gets called before onStop().
To recover your saved state from the Bundle override onRestoreInstanceState() method. This is called after onStart() and before onResume().
Save complex objects
Override onRetainNonConfigurationInstance() and getLastNonConfigurationInstance()
Prior to Honeycomb’s release, the recommended means of transferring active objects across Activity instances was to override the onRetainNonConfigurationInstance() and getLastNonConfigurationInstance() methods. After API level 13 these methods have been deprecated in favor of the more Fragment’s setRetainInstance(boolean) capability, which provides a much cleaner and modular means of retaining objects during configuration changes.
Recommended: Manage complex Object inside a Retained Fragment
Since Fragments introduced from API level 11, the recommended means of retaining active complex objects across Activity instances is to wrap and manage them inside of a retained “worker” Fragment.
In general Fragments are destroyed and recreated along with their parent Activity when a configuration change occurs.
Calling setRetainInstance(true) inside Fragment protect from destroy and recreate and retain the current instance of the fragment when the activity is recreated.
To retain the objects state in a fragment during a runtime configuration change you have to do following steps:
1. Extend the Fragment class and declare references to your stateful objects.
2. Call setRetainInstance(boolean) when the fragment is created.
3. Add the fragment to your activity.
4. Use FragmentManager to retrieve the fragment when the activity is restarted.
Your worker Fragment would look like-
Now you can obtain the data object from the Fragment when the Activity starts again during runtime configuration changes like:
In order to proactively remove the retained worker fragment when you no longer need it, you may check for isFinishing() in onPause() in the activity.
When AsyncTask is running without changing the screen orientation then it will start and finish its work normally. But problems begin to appear when the device orientation is changed while the AsyncTask is in the middle of the work.
The application will crash or java.lang.IllegalArgumentException i.e. View not attached to window manager will be thrown or Activity has leaked window.
To resolve this problem one option is to use IntentService along with BroadCastReceiver to deliver result.
Another option is to run the AsyncTask inside worker Fragment. As explained above using fragments is the cleanest way to handle configuration changes because Fragment has the ability to retain their instances simply by calling setRetainInstance(true) in one of its callback methods.
Hopefully with this article you are familiar with different ways which will help you to handle orientation changes. Use of worker Fragments as a retained Fragments seems hard to understand and looks like a lot of extra work at first but it will also make the user’s experience with your application much better. You can also refer official Android document for more details.
Thanks for reading. To help others please click ❤ to recommend this article if you found it helpful.
Check out my blogger page for more interesting topics on Software development at http://androidjavapoint.blogspot.in
See you soon in the next article!