Android ViewModel Internals: Survive Configuration chages
How ViewModel Survives Configuration Changes in Android - Internal
When building Android apps using Android Jetpack, one of the most important components is the ViewModel. It helps maintain UI-related data across configuration changes such as device rotation.
But the real question is:
How does a ViewModel actually survive when an Activity or Fragment is destroyed and recreated?
To understand this, we need to explore:
ViewModelStore
ViewModelProvider
ComponentActivity internals
NonConfigurationInstance retention in the Android framework
Let's break it down step-by-step.
1. The Problem: Configuration Changes
In Android, when the device rotates or another configuration change occurs, the Android Activity is destroyed and recreated.
Lifecycle flow during rotation:
onPause()
onStop()
onDestroy()Then a new Activity instance is created:
onCreate()
onStart()
onResume()If data were stored directly inside the Activity, it would be lost.
Example:
var userList = mutableListOf<User>()After rotation:
userList → lost
API call → triggered again
UI → reloaded againThis is the problem ViewModel solves.
2. The Core Idea of ViewModel
A ViewModel stores UI-related data outside the Activity/Fragment lifecycle.
Instead of storing data in the Activity:
Activity → ViewModel → DataEven if the Activity is recreated, the ViewModel instance can still be reused.
But where is this ViewModel stored?
That’s where ViewModelStore comes in.
3. ViewModelStore
ViewModelStore is a container that holds ViewModel instances.
Simplified structure:
public class ViewModelStore {
private final HashMap<String, ViewModel> mMap = new HashMap<>();
void put(String key, ViewModel viewModel) {
mMap.put(key, viewModel);
}
ViewModel get(String key) {
return mMap.get(key);
}
void clear() {
for (ViewModel vm : mMap.values()) {
vm.clear(); // triggers onCleared()
}
mMap.clear();
}
}Internally it works like:
ViewModelStore
|
|---- "MainViewModel" → ViewModel instanceEach Activity or Fragment owns a ViewModelStore.
4. ViewModelStoreOwner
Both Activity and Fragment implement:
ViewModelStoreOwnerInterface:
interface ViewModelStoreOwner {
fun getViewModelStore(): ViewModelStore
}Because of this, we can write:
ViewModelProvider(this)Inside either Activity or Fragment.
5. ViewModelProvider
ViewModelProvider is responsible for creating or retrieving a ViewModel from the ViewModelStore.
Simplified logic:
class ViewModelProvider {
fun <T : ViewModel> get(key: String, factory: Factory): T {
if (store.containsKey(key)) {
return store.get(key) as T
} else {
val vm = factory.create()
store.put(key, vm)
return vm
}
}
}So when you request a ViewModel:
ViewModelProvider
|
Check ViewModelStore
|
If exists → return existing instance
Else → create new ViewModel6. ComponentActivity and ViewModelStore
AppCompatActivityextends ComponentActivity, which manages the ViewModelStore.
Key implementation:
@MainThread
public ViewModelStore getViewModelStore() {
if (mViewModelStore == null) {
NonConfigurationInstances nc =
(NonConfigurationInstances) getLastNonConfigurationInstance();
if (nc != null) {
mViewModelStore = nc.viewModelStore;
} else {
mViewModelStore = new ViewModelStore();
}
}
return mViewModelStore;
}
Important method used here:
getLastNonConfigurationInstance()This method retrieves objects saved across configuration changes.
7. NonConfigurationInstances
Android provides a mechanism to retain objects across configuration changes.
This is done through an internal container called:
NonConfigurationInstances
Structure:
NonConfigurationInstances
|
|--- ViewModelStore
|--- other retained objects
Before the Activity is destroyed, Android calls:
onRetainNonConfigurationInstance()ComponentActivity overrides this method.
8. onRetainNonConfigurationInstance()
Implementation:
@Override
public Object onRetainNonConfigurationInstance() {
NonConfigurationInstances nci = new NonConfigurationInstances();
nci.viewModelStore = mViewModelStore;
return nci;
}This method returns an object that Android temporarily stores in memory.
So before destruction:
Activity
|
|--- ViewModelStoreBecomes:
NonConfigurationInstances
|
|--- ViewModelStoreThis object is saved by the framework.
9. Framework Internals
Inside the Android framework, this retention happens through:
ActivityThreadInternal flow:
ActivityThread
|
performDestroyActivity()
|
retainNonConfigurationInstances()
|
NonConfigurationInstances savedThen when the new Activity is created:
ActivityThread.performLaunchActivity()The previously saved instance is attached to the new Activity:
newActivity.mLastNonConfigurationInstances = oldInstance10. Activity Recreation Flow
Full lifecycle during rotation:
Activity A created
|
ViewModelStore created
|
User rotates screen
|
onRetainNonConfigurationInstance()
|
ViewModelStore saved
|
Activity A destroyed
|
Activity B created
|
getLastNonConfigurationInstance()
|
ViewModelStore restored
|
ViewModelProvider returns same ViewModel
So the ViewModel instance never gets destroyed during rotation.
11. When ViewModel Is Actually Destroyed
ViewModel survives configuration changes only.
But if the Activity finishes permanently:
User presses back
Activity finishedThen:
ViewModelStore.clear()Which triggers:
ViewModel.onCleared()Example:
override fun onCleared() {
super.onCleared()
}Used for:
cancelling coroutines
closing resources
removing listeners
12. Process Death Case
If the system kills the app due to low memory:
Process killed
Memory cleared
ViewModelStore lostNothing survives.
This is why we use:
SavedStateHandle
database
datastore
for persistent state.
13. Fragment ViewModel Behavior
Fragments also support ViewModel.
Two common scopes:
Fragment Scope
Fragment → ViewModelDestroyed when fragment is removed.
Activity Scope
Activity
|
|--- Shared ViewModel
|
|--- Fragment A
|--- Fragment BFragments share the same ViewModel instance.
Visual Flow
Old Activity
|
|---- ViewModelStore
|
|---- ViewModel
↓ Rotation
New Activity
|
|---- Reuses ViewModelStore
|
|---- Same ViewModel instance
Interview Summary
How does ViewModel survive configuration changes?
Answer:
ViewModel survives configuration changes because it is stored inside a ViewModelStore owned by the Activity or Fragment. During configuration changes, the system calls onRetainNonConfigurationInstance() and saves the ViewModelStore inside a NonConfigurationInstances object. When the Activity is recreated, the previously retained ViewModelStore is restored and reused by ViewModelProvider, which returns the same ViewModel instance.
ActivityThread
→ performDestroyActivity
→ retainNonConfigurationInstances
→ NonConfigurationInstances
→ ViewModelStore
→ ViewModelProvider
Comments (0)
No comments yet. Be the first to share your thoughts!
Leave a Comment
Get the latest updates
Join our newsletter and never miss an article.