Wrong way 1: Instantiate a ViewModel

Instantiate a ViewModel in a @Composable function

class MainViewModel() : ViewModel() {
    val title = mutableStateOf("Title")
    val count = mutableStateOf(0)
}

@Composable
fun MainScreen() {
    val viewmodel = MainViewModel()

    TextButton(onClick = {
        viewmodel.incrementCount()
    }) {
        Text(text = "incrementCount")
    }
    Text(text = viewmodel.count.value.toString())
}

After we test our code , we found that the count of our Text component has not changed regardless how many times we click the TextButton . The reason behind it is that if a state inside a @Composable function has been changed, it will trigger Recomposition to keep fresh UI , while the process of recomposition is to execute the @Composable function again.

In this case, Text in our @Composable MainScreen observes a count state of ViewModel. When we click the button, the count will be incremented by 1 and trigger a Recomposition .

MainScreen function will be executed again. At the same time, a new MainViewModel will be created. Text read the count state of the new MainViewModel. Obviously, the count should be 0, since each time count state has been updated, MainScreen will create a new ViewModel .

1.gif

Wrong way 2: remember a ViewModel

In Compose, we can remember something like states or objects which are created at the first execution of a @Composable function. When this function is recomposed, these kinds of remembered stuffs will not be created again. So far, Using remember to avoid recreation of our MainViewModel looks like a good solution.

@Composable
fun MainScreen() {
    val viewmodel = remember { MainViewModel() }

    Column(horizontalAlignment = CenterHorizontally) {
        
        Text(text = viewmodel.count.value.toString())
        TextButton(onClick = {
            viewmodel.incrementCount()
        }) {
            Text(text = "Click to Increase")
        }
    }
}

After running these updated code, we found that it works correctly, the count has been increased and Text also displayed the updated count.

2.gif

Does this solution work in all situations?The answer is not at all, imagine that users change configuration of their device, such as language, screen orientation. The Activity will be destroyed and recreated, furthermore ,the view tree will also be recreated.