ViewModel Jetpack Compose Android Simple Example

Home » Jetpack Compose » ViewModel Jetpack Compose Android Simple Example

In Android app development, managing and preserving UI state across configuration changes and screen rotations has always been a challenge. However, with the introduction of ViewModel in Jetpack Compose, handling this task has become much more manageable.

ViewModel in Jetpack Compose simplifies the process of managing and preserving UI state, allowing developers to focus on creating robust and responsive applications.

There are several significant benefits of using ViewModel in app development.

What is ViewModel in Android ?

ViewModel is a component in Android that is designed to store and manage UI-related data in a lifecycle-aware manner.

It acts as a bridge between the UI and the underlying data sources, such as a database or network repository.

The purpose of ViewModel is to separate the concerns of data management and UI presentation, ensuring that the data remains available and preserved during configuration changes, such as screen rotations or activity restarts.

ViewModel Jetpack Compose Android Simple Example

Why do we need ViewModel?

ViewModels are specifically designed to preserve UI-related data across configuration changes, such as screen rotations or system re-creations.

By storing data in a ViewModel, you ensure that the data remains intact and accessible to the UI components even during such events.

This enables a seamless user experience by retaining the UI state.

Let’s build a counter app using ViewModel

Create a new Jetpack Compose app using Android Studio (Flamingo | 2022.2.1)

Let’s create a new file MyViewModel.kt (viewmodels>MyViewModel.kt)

  • Define the ViewModel
package com.example

import androidx.compose.runtime.State
import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel

class MyViewModel: ViewModel() {
    private val _counter = mutableStateOf(0)
    val counter: State<Int> get() = _counter
    fun incrementCounter()
    {
        _counter.value++
    }
    fun decrementCounter()
    {
        _counter.value--
    }
}

In this example, we define a simple ViewModel called MyViewModel, which holds a counter as its state using mutableStateOf. The incrementCounter function is responsible for incrementing the counter value. Besides, the decrementCounter() function is responsible for decrementing the counter value.

Let’s utilize the ViewModel within the Composable function

@Composable
fun MyScreen(viewModel: MyViewModel)
{
    val counterState = viewModel.counter
    Column(modifier = Modifier.fillMaxSize().padding(16.dp),
        verticalArrangement = Arrangement.Center,
        horizontalAlignment = Alignment.CenterHorizontally
    ) {

        Text(text = "Counter: ${counterState.value}")
        Button(onClick = {viewModel.incrementCounter()}) {
            Text("Increment")
        }
        Button(onClick = {viewModel.decrementCounter()}) {
            Text(text = "Decrement")
        }
    }
}

Let’s observe the ViewModel

 private val viewModel: MyViewModel by viewModels()

The statement is using the viewModels() delegate from the AndroidX lifecycle library to initialize and assign an instance of MyViewModel to the viewModel property.

MainActivity.kt

class MainActivity : ComponentActivity() {
    private val viewModel: MyViewModel by viewModels()
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            NoteAppTheme {
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colorScheme.background
                ) {
                   MyScreen(viewModel = viewModel)
                }
            }
        }
    }
}

How to preview viewmodel in jetpack compose (@Preview) ?

Create a preview-specific ViewModel instance


@Preview(showBackground = true)
@Composable
fun GreetingPreview() {
    NoteAppTheme {
        val previewViewModel = MyViewModel()
        MyScreen(viewModel = previewViewModel)

    }
}

Complete code of MainActivity.kt

package com.example

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.viewModels
import androidx.compose.foundation.layout.Arrangement

import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Button
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.example.ui.theme.NoteAppTheme
import com.example.viewmodels.MyViewModel

class MainActivity : ComponentActivity() {
    private val viewModel: MyViewModel by viewModels()
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            NoteAppTheme {
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colorScheme.background
                ) {
                   MyScreen(viewModel = viewModel)
                }
            }
        }
    }
}



@Composable
fun MyScreen(viewModel: MyViewModel)
{
    val counterState = viewModel.counter
    Column(modifier = Modifier.fillMaxSize().padding(16.dp),
        verticalArrangement = Arrangement.Center,
        horizontalAlignment = Alignment.CenterHorizontally
    ) {

        Text(text = "Counter: ${counterState.value}")
        Button(onClick = {viewModel.incrementCounter()}) {
            Text("Increment")
        }
        Button(onClick = {viewModel.decrementCounter()}) {
            Text(text = "Decrement")
        }
    }
}


@Preview(showBackground = true)
@Composable
fun GreetingPreview() {
    NoteAppTheme {
        val previewViewModel = MyViewModel()
        MyScreen(viewModel = previewViewModel)

    }
}

App demo screenshots

ViewModel Jetpack Compose Android Simple Example Screenshot

You may also like...