How do you handle configuration changes like screen rotations in an Android application?

Handling configuration changes, such as screen rotations, is a common challenge in Android development. Configuration changes can cause your activity to be destroyed and recreated, which may lead to the loss of user data or state. In this blog, we will explore various strategies to handle configuration changes effectively to ensure a seamless user experience.
Understanding Configuration Changes
A configuration change occurs when the device’s current configuration changes, such as when the screen orientation changes, the keyboard is hidden or shown, or the language is changed. By default, Android restarts the activity to apply these changes, which calls the lifecycle methods: onDestroy(), onCreate(), and onStart().
Strategies to Handle Configuration Changes
1. Using onSaveInstanceState and onRestoreInstanceState
The simplest way to handle configuration changes is to save the activity state using onSaveInstanceState and restore it in onRestoreInstanceState or onCreate.
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
// Save data to outState bundle
outState.putString("KEY", "value")
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// Restore data from savedInstanceState bundle
if (savedInstanceState != null) {
val value = savedInstanceState.getString("KEY")
}
}
2. Retaining Fragments
Fragments can be retained across configuration changes by calling setRetainInstance(true) in the fragment. This method prevents the fragment from being destroyed and recreated during a configuration change.
Example:
class MyFragment : Fragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Retain this fragment across configuration changes
retainInstance = true
}
}
3. ViewModel
Using ViewModel is a recommended approach for handling configuration changes. A ViewModel is designed to store and manage UI-related data in a lifecycle-conscious way, allowing data to survive configuration changes.
Example:
class MyViewModel : ViewModel() {
val data: MutableLiveData<String> by lazy {
MutableLiveData<String>()
}
}
class MyActivity : AppCompatActivity() {
private lateinit var viewModel: MyViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// Obtain the ViewModel
viewModel = ViewModelProvider(this).get(MyViewModel::class.java)
// Observe ViewModel data
viewModel.data.observe(this, Observer { value ->
// Update UI with data
})
}
}
4. Handling Configuration Changes Manually
You can handle configuration changes manually by specifying the configChanges attribute in your AndroidManifest.xml and overriding the onConfigurationChanged method.
Example:
<activity android:name=".MyActivity" android:configChanges="orientation|screenSize"> </activity>
override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
// Handle the configuration change
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
// Handle landscape mode
} else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
// Handle portrait mode
}
}
5. Saving UI State with View Binding or Data Binding
View Binding and Data Binding libraries can simplify state management. For example, you can use Data Binding to automatically update the UI when the underlying data changes, making it easier to restore the state after a configuration change.
Example:
<!-- activity_main.xml -->
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="viewModel"
type="com.example.app.MyViewModel" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{viewModel.data}" />
</LinearLayout>
</layout>
class MyActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private lateinit var viewModel: MyViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
viewModel = ViewModelProvider(this).get(MyViewModel::class.java)
binding.viewModel = viewModel
binding.lifecycleOwner = this
}
}
Conclusion
Handling configuration changes effectively is essential for creating a robust and user-friendly Android application. Whether you choose to use onSaveInstanceState, retain fragments, leverage ViewModel, handle changes manually, or utilize data binding, each method has its advantages and is suitable for different scenarios. By implementing these strategies, you can ensure that your application remains stable and provides a seamless experience to your users, even during configuration changes.
For more tips and tutorials on Android development, stay tuned to our blog. If you have any questions or need further clarification, feel free to leave a comment below!
Read More :





