LibraryCreating a ViewModel

Creating a ViewModel

Learn about Creating a ViewModel as part of Kotlin Android Development and Play Store Publishing

Understanding ViewModels in Kotlin Android Development

In modern Android development with Kotlin, the Model-View-ViewModel (MVVM) architectural pattern is a cornerstone for building robust, maintainable, and testable applications. A key component of MVVM is the ViewModel, which acts as a bridge between the UI (View) and the data (Model). This guide will walk you through the fundamentals of creating and utilizing ViewModels, setting the stage for successful Play Store publishing.

What is a ViewModel?

A ViewModel is a class designed to store and manage UI-related data in a lifecycle-aware manner. Unlike Activities or Fragments, which are tied to the UI lifecycle and can be destroyed and recreated (e.g., during configuration changes like screen rotation), a ViewModel survives configuration changes. This means it can hold data that the UI needs, and the UI can observe changes to that data without losing it.

ViewModels decouple UI logic from UI controllers.

ViewModels hold UI data and business logic, making your Activities and Fragments simpler and more focused on displaying information and handling user input.

By separating the data management and business logic into a ViewModel, your Activities and Fragments become primarily responsible for observing data changes from the ViewModel and updating the UI accordingly. This separation of concerns leads to cleaner code, easier testing, and better management of UI states, especially during complex user interactions or data loading scenarios.

Key Benefits of Using ViewModels

Using ViewModels offers several significant advantages for Android development:

FeatureBenefitImpact on Development
Lifecycle AwarenessSurvives configuration changesPrevents data loss and unnecessary reloads
Separation of ConcernsDecouples UI logic from UI controllersImproves code readability, testability, and maintainability
Data ManagementCentralized place for UI-related dataSimplifies data handling and state management
TestabilityEasier to unit test without UI dependenciesFaster and more reliable testing cycles

Creating Your First ViewModel

To create a ViewModel in Kotlin, you'll typically extend the

code
ViewModel
class from the Android Architecture Components. You'll also need to add the necessary dependency to your app's
code
build.gradle
file.

What is the primary class to extend when creating a ViewModel in Android?

The ViewModel class from the Android Architecture Components.

Here's a basic example of a ViewModel that holds a counter value:

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

class CounterViewModel : ViewModel() {

    // MutableLiveData is private to prevent external modification
    private val _count = MutableLiveData<Int>()
    val count: LiveData<Int> get() = _count // Public LiveData for observation

    init {
        // Initialize the count
        _count.value = 0
    }

    fun increment() {
        val currentCount = _count.value ?: 0
        _count.value = currentCount + 1
    }

    fun decrement() {
        val currentCount = _count.value ?: 0
        _count.value = currentCount - 1
    }
}

This CounterViewModel uses MutableLiveData to hold the _count value. LiveData is an observable data holder class that is lifecycle-aware. The UI can observe the count property, and when its value changes, the UI will be notified and can update itself. The init block is used for initial setup.

📚

Text-based content

Library pages focus on text content

Observing ViewModel Data in the UI

In your Activity or Fragment, you'll obtain an instance of your ViewModel and then observe its

code
LiveData
. When the
code
LiveData
changes, the observer's
code
onChanged
method is called, allowing you to update the UI elements.

Here's how you might observe the

code
count
in an Activity:

Loading diagram...

kotlin
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import android.widget.TextView
import androidx.lifecycle.ViewModelProvider
class MainActivity : AppCompatActivity() {
private lateinit var viewModel: CounterViewModel
private lateinit var countTextView: TextView
private lateinit var incrementButton: Button
private lateinit var decrementButton: Button
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
countTextView = findViewById(R.id.countTextView)
incrementButton = findViewById(R.id.incrementButton)
decrementButton = findViewById(R.id.decrementButton)
// Get an instance of the ViewModel
viewModel = ViewModelProvider(this).get(CounterViewModel::class.java)
// Observe the LiveData from the ViewModel
viewModel.count.observe(this) { count ->
countTextView.text = count.toString()
}
// Set up button click listeners to call ViewModel methods
incrementButton.setOnClickListener {
viewModel.increment()
}
decrementButton.setOnClickListener {
viewModel.decrement()
}
}
}

ViewModelFactory for Dependencies

If your ViewModel requires dependencies (e.g., a repository for data fetching), you'll need to create a

code
ViewModelProvider.Factory
. This factory is responsible for creating instances of your ViewModel and injecting its dependencies.

Using a ViewModelFactory is crucial for dependency injection, making your ViewModels more testable and manageable.

Example of a ViewModelFactory:

kotlin
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
class CounterViewModelFactory(private val initialCount: Int) : ViewModelProvider.Factory {
override fun create(modelClass: Class): T {
if (modelClass.isAssignableFrom(CounterViewModel::class.java)) {
@Suppress("UNCHECKED_CAST")
return CounterViewModel(initialCount) as T
} // You would need to modify CounterViewModel to accept initialCount
throw IllegalArgumentException("Unknown ViewModel class")
}
}
// Modified CounterViewModel to accept initial count
// class CounterViewModel(initialCount: Int) : ViewModel() { ... }
// In Activity:
// val factory = CounterViewModelFactory(10)
// viewModel = ViewModelProvider(this, factory).get(CounterViewModel::class.java)

Next Steps: Play Store Publishing

Understanding ViewModels is a fundamental step towards building production-ready Android applications. When preparing for Play Store publishing, a well-structured app using MVVM with ViewModels ensures better performance, stability, and user experience. This architecture also simplifies future updates and feature additions, making your app more sustainable in the long run.

Learning Resources

ViewModel Overview | Android Developers(documentation)

The official Android Developers documentation provides a comprehensive overview of the ViewModel class, its lifecycle, and best practices.

ViewModel | Android Developers(documentation)

Direct API reference for the ViewModel class, detailing its methods and properties.

LiveData Overview | Android Developers(documentation)

Learn about LiveData, an observable data holder class that is lifecycle-aware, and how it integrates with ViewModels.

ViewModelFactory | Android Developers(documentation)

Explains how to use ViewModelProvider.Factory to provide dependencies to your ViewModels.

Android Architecture Components: ViewModel(video)

A video tutorial from Google Developers explaining the ViewModel component and its benefits.

MVVM Architecture in Android with Kotlin(blog)

A detailed blog post explaining the MVVM pattern in Android using Kotlin, including ViewModel implementation.

Kotlin Coroutines and Flow with ViewModel(documentation)

Learn how to integrate Kotlin Coroutines and Flow with ViewModels for asynchronous data handling.

Testing ViewModels | Android Developers(documentation)

Guidance on how to effectively unit test your ViewModels.

Android Jetpack: ViewModel(documentation)

Information about the Android Jetpack Lifecycle library, which includes ViewModel and LiveData.

What is MVVM? (Model-View-ViewModel)(video)

An introductory video explaining the MVVM architectural pattern in general terms.