Android Studio Guide to ViewModel & LiveData (2020 Edition)

A few years ago at Google I/O it was announced that Android is taking a new approach to software architecture, starting with the idea that Android app development should be more opinionated. Revealed at the conference was a pair of libraries developed by Google for Android Engineers to incorporate into their apps. I immediately began reading about “Jetpack” and build apps incorporating the new libraries, ViewModel and LiveData. In this blog post we’ll see how the pieces fit together and how we can build our first app using both of these classes. Ready? Let’s begin!

To begin using ViewModel and LiveData we first need to add the required dependencies to our build.gradle file. Open the Gradle file and paste in the following.

apply plugin: 'com.android.application'

apply plugin: 'kotlin-android'

apply plugin: 'kotlin-android-extensions'

// Daniel says add this line:
apply plugin: 'kotlin-kapt'

android {
    compileSdkVersion 29
    defaultConfig {
        applicationId "com.danielmalone.dating"
        minSdkVersion 21
        targetSdkVersion 29
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

    kotlinOptions {
        jvmTarget = JavaVersion.VERSION_1_8.toString()
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
    implementation 'androidx.appcompat:appcompat:1.1.0'
    implementation 'androidx.core:core-ktx:1.2.0'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    implementation 'com.google.android.material:material:1.1.0'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test.ext:junit:1.1.1'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'

    // Daniel says add these four line:
    implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0"
    implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.2.0"
    kapt "androidx.lifecycle:lifecycle-compiler:2.2.0"
    implementation "androidx.activity:activity-ktx:1.1.0"
}

Create a new class that extends ViewModel:

package com.danielmalone.dating

import androidx.lifecycle.ViewModel

class MainActivityViewModel : ViewModel() {
}

Now this class doesn’t do anything yet. Let’s add some LiveData variables that will later be observed in our MainActivity. With MVVM it’s best practices to have one ViewModel per Activity or Fragment, just like you would have one Presenter per class in MVP.

package com.danielmalone.dating

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

class MainActivityViewModel : ViewModel() {

    val firstName = MutableLiveData<String>()
    val lastName = MutableLiveData<String>()
    val age = MutableLiveData<Int>()
}

In MainActivity we can now “observe” our firstName, receiving an alert — with a value like “Daniel” — every time the variable changes. If firstName changes from Daniel to John to Nate, we’ll get three different Strings. Here’s our Activity:

package com.danielmalone.dating

import android.os.Bundle
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.Observer
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {

    val viewModel: MainActivityViewModel by viewModels()

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

        viewModel.firstName.observe(this, Observer {

        })
    }
}

Notice how we setup our viewModel variable at the top using by viewModels(), part of the KTX library provided by Google. See the build.gradle file above for the import line (it’s near the bottom in the file). After the setup is complete, we’re free to use viewModel in onCreate. To observe data, simply type viewModel.firstName.observe, passing in this (or activity if you’re using a Fragment) followed by the Observer lambda. Every time firstName gets changed, we can handle the UI changes between the { } symbols. Let’s give it a try!

        viewModel.firstName.observe(this, Observer {
            firstNameTextView.text = it
        })

If your XML layout has a TextView with an id of firstNameTextView, the firstName will become the TextView‘s text, appearing on the screen for users to see. But we can observe more than just one LiveData instance. We can observe and update multiple LiveData objects however many times we wish. Here’s an example ViewModel:

package com.danielmalone.dating

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

class MainActivityViewModel : ViewModel() {

    val firstName = MutableLiveData<String>()
    val lastName = MutableLiveData<String>()
    val age = MutableLiveData<Int>()

    fun setup(profileId: String) {
        // Daniel says make an api call to a server here. For now we'll fake it.
        val apiFirstName = "Daniel"
        val apiLastName = "Malone"
        val apiAge = 28
        firstName.value = apiFirstName
        lastName.value = apiLastName
        age.value = apiAge
    }
}

And an example Activity that observes these values:

package com.danielmalone.dating

import android.os.Bundle
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.Observer
import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.android.synthetic.main.content_main.*

class MainActivity : AppCompatActivity() {

    private val viewModel: MainActivityViewModel by viewModels()

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

        viewModel.firstName.observe(this, Observer {
            firstNameTextView.text = it
        })

        viewModel.lastName.observe(this, Observer {
            lastNameTextView.text = it
        })

        viewModel.age.observe(this, Observer {
            ageTextView.text = it.toString()
        })
    }
}

Stay tuned for part two as we dive more into ViewModel and LiveData!

Daniel Malone Daniel Malone
Bringing more than a decade of software engineering experience, Daniel Malone is Editor at androidEveryday. An Austin native, Daniel is often found reading technical books, blogging and creating YouTube tutorials. When not working, he likes to listen to pop hits on Google Play Music.

Android RecyclerView Tutorial (Part 1)

  • Most apps contain lists of data using RecyclerView.
  • In this tutorial, use ConstraintLayout and Kotlin to display a list of data.

2 years ago

findViewById() in Kotlin

  • As you may have discovered, findViewByid() is no longer needed.
  • Kotlin adds the ability to directly access Views.

2 years ago

Android Architecture Components Tutorial: ViewModel + LiveData

  • Use Kotlin to build a basic Android app using Android Architecture Components.
  • As part of Jetpack, LiveData and ViewModel support a MVVM app architecture.

2 years ago

Android SharedPreferences Tutorial in Kotlin

  • Use SharedPreferences to store simple data in Android Studio projects.
  • It's good for storing small amounts of data

    2 years ago

Cleaner Architecture for Android Apps

  • Clean Architecture for Android can help developers prepare for change.
  • But app developers can't possibly know what will change.

    2 years ago

Android RecyclerView with Kotlin – Part 3

  • In part three of this series, finish creating the RecyclerView.
  • Use onBindViewHolder to display data.

2 years ago

Android RecyclerView with Kotlin – Part 2

  • Create the entire RecylerView for our UsersAdapter.
  • Continued from part 1, where we set up the Android Studio project.

2 years ago

Android and RxJava: Using a Single

  • Use RxJava's Single class when the expected type is either a success or error.
  • It's only slightly different from Observable.just(), which we discussed in the last article.

2 years ago

Android and RxJava: Getting Started

  • The powerful library RxJava can help developers build better apps.
  • See how to use Observables and Observers in this tutorial.

2 years ago

Android RecyclerView with Kotlin - Part 1

  • Oftentimes, developers need to display a list of some sort of data.
  • Whatever type of data is displayed, you should use a RecyclerView.

2 years ago

Display Sample Data when Creating a RecyclerView

  • Android Studio's default RecyclerView preview lacks sample data.
  • Adding sample data can be helpful for debugging.

2 years ago

Android Studio Tutorial with Kotlin (2018 Edition) - Part 2

  • Create a UI in Android Studio using the Design mode.
  • In this latest installment for beginners, we'll add a widget to our screen.

2 years ago