Understanding Configuration Changes and ViewModel in Android
1. What Are Configuration Changes?
Configuration changes occur when the device environment changes in a way that affects the UI. Common configuration changes in Android include:
When a configuration change occurs, Android:
This destruction and recreation wipe out any in-memory data Activity by default, which is why data resets with configuration changes unless managed properly.
2. The Role of ViewModel in Managing Data
The ViewModel component in Android Architecture Components is designed to persist data across configuration changes. Unlike an Activity or Fragment, a ViewModel survives the recreation of the UI, allowing data to be retained across these changes.
How ViewModel Works
Benefits of ViewModel
3. Example: A Counter App Using ViewModel
Let’s create a simple counter app to demonstrate how ViewModel retains data across configuration changes.
Step 1: Create a ViewModel to Hold Data
class CounterViewModel : ViewModel() {
private var _counter = MutableLiveData(0)
val counter: LiveData<Int> get() = _counter
fun incrementCounter() {
_counter.value = (_counter.value ?: 0) + 1
}
}
Step 2: Set up ViewModel in an Activity
class CounterActivity : AppCompatActivity() {
private lateinit var viewModel: CounterViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_counter)
// Obtain ViewModel instance
viewModel = ViewModelProvider(this).get(CounterViewModel::class.java)
// Observe counter data and update the UI
viewModel.counter.observe(this) { count ->
counterTextView.text = count.toString()
}
// Increment counter on button click
incrementButton.setOnClickListener {
viewModel.incrementCounter()
}
}
}
In this example:
领英推荐
4. ViewModelProvider and ViewModelProvider.Factory
ViewModelProvider
The ViewModelProvider is responsible for creating and retrieving ViewModel instances. When ViewModelProvider is used:
ViewModelProvider.Factory
If a ViewModel requires dependencies, such as a repository, ViewModelProvider.Factory can be used to handle this dependency injection.
Example with Factory Pattern
class CounterViewModelFactory(private val repository: CounterRepository) : ViewModelProvider.Factory {
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
if (modelClass.isAssignableFrom(CounterViewModel::class.java)) {
return CounterViewModel(repository) as T
}
throw IllegalArgumentException("Unknown ViewModel class")
}
}
Usage in Activity
class CounterActivity : AppCompatActivity() {
private lateinit var viewModel: CounterViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_counter)
val repository = CounterRepository()
val factory = CounterViewModelFactory(repository)
viewModel = ViewModelProvider(this, factory).get(CounterViewModel::class.java)
// Observe counter data and update the UI
viewModel.counter.observe(this) { count ->
counterTextView.text = count.toString()
}
// Increment counter on button click
incrementButton.setOnClickListener {
viewModel.incrementCounter()
}
}
}
With this approach, you can pass in dependencies when creating the ViewModel, ensuring it has the resources it needs.
5. How ViewModel Works Behind the Scenes
6.Lifecycle Management
Summary
Using ViewModel ensures that your app’s data persists across configuration changes, improving the user experience by eliminating data loss and making your app more resilient to environmental changes.