Android ViewModel Example - Build Your First ViewModel with Kotlin

One of the most common challenges in Android development is keeping your UI data intact when the device configuration changes — a screen rotation, keyboard appearing, or language switch. Without the right approach, your app loses data, shows stale UI, or crashes entirely.

ViewModels are the solution. Part of Android's MVVM (Model-View-ViewModel) architecture, they store and manage UI-related data independently of the Activity or Fragment lifecycle. In this guide you'll build your first ViewModel step by step, understand when and why to use it, and learn best practices that apply to real-world apps.

Android ViewModel Example

Android ViewModel — managing UI data across configuration changes

Prerequisites: This guide assumes basic knowledge of Kotlin and Android Activities. If you're new to Android development, start with our Android Development with Kotlin beginner guide first.

What is a ViewModel?

A ViewModel is an architecture component designed to store and manage UI-related data in a lifecycle-aware way. It lives as long as its associated Activity or Fragment is alive — and crucially, it survives configuration changes like screen rotation.

Without ViewModel, every time you rotate your screen the Activity is destroyed and recreated, wiping out any data you were holding in it. With ViewModel, the data stays in memory and your UI simply re-attaches to the existing ViewModel.

  • Configuration Change Survivor: Persists through rotation, keyboard changes, and language switches
  • Lifecycle-Aware: Automatically cleaned up when the Activity is permanently finished — no memory leaks
  • Separation of Concerns: Keeps UI logic out of Activity/Fragment, making code cleaner and easier to test
  • Works with LiveData & StateFlow: Exposes data reactively so the UI always stays up to date — learn more in our LiveData and ViewModel guide

The Problem: Configuration Changes

When a configuration change occurs, Android destroys and recreates your Activity. This triggers the full lifecycle: onDestroy()onCreate(). Any data stored directly in the Activity is lost.

Common configuration changes that cause this:

  • Screen rotation — portrait to landscape and vice versa
  • Keyboard visibility — soft keyboard appearing or disappearing
  • Language/Locale change — switching between languages
  • Dark/Light mode toggle — theme changes at runtime

ViewModel solves this by living outside the Activity's lifecycle scope. For a deeper look at how this works, read our ViewModel Lifecycle guide.

Building Your First ViewModel — Step by Step

Step 1: Add the dependency

Add the ViewModel KTX dependency to your build.gradle (app) file:

// build.gradle (app)
dependencies {
    implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.0"
    implementation "androidx.activity:activity-ktx:1.9.0"
}

Step 2: Create your ViewModel class

Create a new Kotlin file MyViewModel.kt and extend ViewModel(). Use MutableLiveData privately and expose immutable LiveData publicly — this prevents the UI from directly modifying state.

import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel

class MyViewModel : ViewModel() {

    // Private mutable — only ViewModel modifies this
    private val _myData = MutableLiveData<String>()

    // Public immutable — UI observes this
    val myData: LiveData<String> = _myData

    fun loadData() {
        // Simulate loading data (e.g. from a repository)
        _myData.value = "Hello from ViewModel!"
    }
}

Step 3: Access the ViewModel in your Activity

Use the by viewModels() Kotlin property delegate — the simplest and recommended way to get a ViewModel in an Activity. It automatically scopes the ViewModel to the Activity's lifecycle.

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.activity.viewModels

class MainActivity : AppCompatActivity() {

    // Scoped to this Activity — survives rotation automatically
    private val viewModel: MyViewModel by viewModels()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // Observe LiveData — updates UI whenever data changes
        viewModel.myData.observe(this) { data ->
            binding.tvMessage.text = data
        }

        // Trigger data load
        viewModel.loadData()
    }
}

Step 4: Access ViewModel in a Fragment

In a Fragment, use by viewModels() for a Fragment-scoped ViewModel, or by activityViewModels() to share the same ViewModel instance with the host Activity — useful for sharing data between fragments.

import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.fragment.app.activityViewModels

class MyFragment : Fragment() {

    // Fragment-scoped ViewModel (separate instance from Activity)
    private val fragmentViewModel: MyViewModel by viewModels()

    // Activity-scoped ViewModel (shared with Activity and other Fragments)
    private val sharedViewModel: MyViewModel by activityViewModels()

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        sharedViewModel.myData.observe(viewLifecycleOwner) { data ->
            // Update UI
        }
    }
}

Step 5: Update your layout

Make sure your activity_main.xml has a TextView to display the data:

<TextView
    android:id="@+id/tvMessage"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Loading..."
    android:textSize="18sp"/>

by viewModels() vs ViewModelProvider — What's the Difference?

Both achieve the same result but by viewModels() is the modern, concise Kotlin way:

Approach Code Recommended?
by viewModels() private val vm: MyVM by viewModels() ✅ Yes — modern Kotlin
ViewModelProvider ViewModelProvider(this)[MyVM::class.java] ⚠️ Use when passing custom factory
by activityViewModels() private val vm: MyVM by activityViewModels() ✅ Yes — for sharing between fragments

Best Practices

  • Never hold Context or View references in a ViewModel — it outlives the Activity and will cause memory leaks. Use AndroidViewModel if you genuinely need Application context.
  • Expose immutable data — keep MutableLiveData or MutableStateFlow private, expose LiveData or StateFlow publicly.
  • Use LiveData for simple state, StateFlow for complex state — learn the difference in our ViewModel State Management guide.
  • Use viewModelScope for coroutines — it automatically cancels coroutines when the ViewModel is cleared. Learn more in our Kotlin Coroutines guide.
  • One ViewModel per screen — don't share a single ViewModel across unrelated screens. Use by activityViewModels() only for genuinely shared data between fragments on the same screen.

Frequently Asked Questions

Does ViewModel survive process death (app killed by system)?
No — ViewModel only survives configuration changes. If the system kills the process due to low memory, ViewModel data is lost. For that use case, combine ViewModel with SavedStateHandle. See our State Management guide for details.

Can I use ViewModel with Jetpack Compose?
Yes — use the viewModel() composable from androidx.lifecycle:lifecycle-viewmodel-compose to get a ViewModel in any composable function.

When is a ViewModel destroyed?
When the Activity is permanently finished (user presses back or calls finish()). Not during rotation or configuration changes. Read more about the ViewModel lifecycle here.

Can I pass constructor arguments to a ViewModel?
Yes — use a ViewModelFactory or Hilt's @HiltViewModel with @Inject constructor for dependency injection.

Summary
  • ViewModels survive configuration changes — no more data loss on rotation
  • Use by viewModels() in Activity, by activityViewModels() to share between fragments
  • Always expose immutable LiveData/StateFlow to the UI
  • Never hold Context or View references inside a ViewModel
  • Use viewModelScope for coroutines inside ViewModel
  • For state that survives process death, use SavedStateHandle
📚 Continue Learning

Pragnesh Ghoda

A forward-thinking developer offering more than 8 years of experience building, integrating, and supporting android applications for mobile and tablet devices on the Android platform. Talks about #kotlin and #android

1 Comments

Please let us know about any concerns or query.

Previous Post Next Post

Contact Form