Go back

ViewModels & Configuration Changes In Android

Published on 8 May, 2025

An Activity in android are nothing but a screen which a user can see and interact with. Now in previous post we have seen that activities has multiple lifecycle stages. However, in that post, I only specified about those methods in context of opening, closing and navigation of those activites.

But, there’s one big enemy of activities, that can cause activities to destroy and reload completely, hence making them loose all their data. Can you guess? Well this big enemy is known as Configuration Change.

What are Configuration Changes

Whenever we change some configuration of our android device, such as we rotate the device or change the theme of our device, the activities are restarted or recreated from start. This will cause a user to loose entire data if all of a sudden some configuration change occurs.

Some common (not all) configuration changes includes:

  1. App display size
  2. Screen orientation
  3. Font size and weight
  4. Language change
  5. Dark mode versus light mode
  6. Keyboard availability
  7. Resizing Windows

These configuration changes can essentially cause an activity to be recreated. So, what can we do? Well there’s a hacky way in androidManifest.xml by specifying configChanges as shown below.

<activity
    android:name=".MyActivity"
    android:configChanges="orientation|screenSize|screenLayout|keyboardHidden"
    android:label="@string/app_name">

However, this should be used as last resort or for a very special usecase. So, who will protect our activities from such a dangerous enemy? Who will save us? Well, We have a hero, ViewModels.

What is ViewModel

A ViewModel is a special class, that holds the UI state and business logic for one or multiple activities. A Viewmodel follows different lifecycle than an activity lifecycle. While an activity can be recreated by an configuration change, the viewmodel will stay in the memory.

The main concept is to delegate the UI state to a special class, that will not be recreated on any small change and once the activity is recreated, it will then use the data from our special class, like nothing happened (but you now know the truth) and hence will persist the user’s data.

From the offical android docs, here’s an image depicting lifecycle of a viewmodel and an activity side by side for better understanding.

ViewModels Lifecycle

You usually request a ViewModel the first time the system calls an activity object’s onCreate() method. The system may call onCreate() several times throughout the existence of an activity, such as when a device screen is rotated. The ViewModel exists from when you first request a ViewModel until the activity is finished and destroyed.

Benifits of using ViewModel

The key benefits of the ViewModel class are essentially two:

  1. It allows you to persist UI state.
  2. It provides access to business logic.

Code Implementation

class BooksViewModel: ViewModel() {

    var numBooks by mutableStateOf(10)
    private set // only viewmodel can modify this state

    fun incBook(){
        numBooks = numBooks + 1
    }

    fun decBook(){
        numBooks = numBooks - 1
    }
}

The above viewmodel is a simple one for explanation. It has a single numBooks state, which signifies number of books. There are two functions incBook and decBook for incrementing/decrementing a book.

To call this from UI.

@Composable
fun BookCounterScreen() {
    val viewModel = viewModel<BooksViewModel>()
    val numBooks = viewModel.numBooks

    Column(
        modifier = Modifier
            .fillMaxSize()
            .padding(16.dp),
        verticalArrangement = Arrangement.Center,
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        Text("Number of books: $numBooks", style = MaterialTheme.typography.headlineMedium)
        Spacer(modifier = Modifier.height(16.dp))
        Row {
            Button(onClick = { viewModel.incBook() }) {
                Text("Add Book")
            }
            Spacer(modifier = Modifier.width(8.dp))
            Button(onClick = { viewModel.decBook() }) {
                Text("Remove Book")
            }
        }
    }
}

Now, we can use the viewModel() and then use this inside our UI. Now even if you rotate your device, change theme or change device’s language, the number of books will not be lost!

Incase, you have some dependency in your viewModel, let’s say for, e.g favBook, then you can initialize your viewModel in the screen like this.

val contactsViewModel = viewModel<BooksViewModel>(
 factory =  object: ViewModelProvider.Factory {
  
  override fun <T as ViewModel> create(modelclass : Class<T>){
   
   return ContactsViewModel(favBook = Harry Potter) as T
  }
 
 }
) 
 implementation 'androidx.lifecycle:lifecycle-viewmodel-compose:2.6.1'

Remember to add above dependency before using this ViewModel() in your screen.

Conclusion

Hence ViewModels are really important for building any complex application. It holds our UI State and Business Logic, Helps persist data across configuration changes and just makes code more maintainable.