Android MVVM: Getting Started

Android Architecture Components + MVVM = Easier Development

Android MVVM: Getting Started

Most design patterns help codebases tolerate change. If you want to come back in six months and fix that bug or add a feature, how hard is it? MVVM is an architecture makes it easier for others -- and even yourself -- to understand code.

To begin, let's add to build.gradle. Because we need ViewModel and LiveData, we have to import them with Gradle. First, confirm that the beginning of build.gradle contains the following.

Note: There are multiple build.gradle files. Edit the Module: app file.
apply plugin: 'com.android.application'

apply plugin: 'kotlin-android'

apply plugin: 'kotlin-android-extensions'

apply plugin: 'kotlin-kapt'

Note the kotlin-kapt line. We need this. Then add these two lines to the dependencies section of the same build.gradle:

    implementation "androidx.lifecycle:lifecycle-extensions:2.0.0"
    kapt "androidx.lifecycle:lifecycle-compiler:2.0.0"

My entire build.gradle file looks like the following.

apply plugin: 'com.android.application'

apply plugin: 'kotlin-android'

apply plugin: 'kotlin-android-extensions'

apply plugin: 'kotlin-kapt'

android {
    compileSdkVersion 28
    defaultConfig {
        applicationId "com.example.androidmvvm"
        minSdkVersion 15
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
    implementation 'androidx.appcompat:appcompat:1.1.0-alpha03'
    implementation 'androidx.core:core-ktx:1.1.0-alpha05'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    implementation 'com.google.android.material:material:1.1.0-alpha05'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test:runner:1.1.2-alpha02'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0-alpha02'
    implementation "androidx.lifecycle:lifecycle-extensions:2.0.0"
    kapt "androidx.lifecycle:lifecycle-compiler:2.0.0"
}

Create a new Kotlin class called MainViewModel and add the following. This is where our complex code will live.

class MainViewModel : ViewModel() {

    val firstName = MutableLiveData<String>()
}

As you can see, we extend ViewModel and create a MutableLiveData of firstName. This firstName is a String (text, not a number).

Open MainActivity.kt and add the following to the onCreate method.

        val model = ViewModelProviders.of(this).get(MainViewModel::class.java)

Directly below this model variable, type the following.

        model.firstName.observe(this, Observer {
            // this is where we will display firstName
        })

Now open content_main.xml and paste in the following code. Here, we have a TextView with an id of nameTextView. This will be the TextView we update with firstName.

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context=".MainActivity"
    tools:showIn="@layout/activity_main">

    <TextView
        android:id="@+id/nameTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

With nameTextView ready, let's update it with the result of firstName from our model:

       model.firstName.observe(this, Observer {
            nameTextView.text = it
        })

When you run the app, you should see... nothing. This is because we haven't yet set the value of firstName. We can fix that now. Add this line to the bottom of onCreate:

        model.firstName.value = "Daniel J Malone"

My complete MainActivity.kt file is below.

package com.example.androidmvvm

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

class MainActivity : AppCompatActivity() {

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

        val model = ViewModelProviders.of(this).get(MainViewModel::class.java)

        model.firstName.observe(this, Observer {
            nameTextView.text = it
        })

        model.firstName.value = "Daniel J Malone"
    }
}
We will expand on this in a future tutorial. Better architecture can make development, especially refactoring, a lot easier.

Run the app, and you should see "Daniel J Malone" shown in the app. Great work!

More Tutorials

Android Basic Alert Dialog Box
Basic CardView

Basic CardView

Material Design.

Rounded Corners with a Border
Rounded Button in Android Studio

Rounded Button in Android Studio

Create beautiful buttons in XML.

RecyclerView Day 3: Invoicing app

RecyclerView Day 3: Invoicing app

Built with Android Studio and Kotlin.

Build a Ridesharing Android App - Part 1

Build a Ridesharing Android App - Part 1

Getting started is sometimes the hardest part.

setOnClickListener

Add a click listener in Kotlin.

Android Login Layout

Let users sign in.

Registration Screen

Registration Screen

It always begins with registration.