LiveData in Android Tutorial

Hey technoz, hope you are doing good in your coding life and other aspects also. Well, Here I am to share the knowledge about one of the most important and hot topic in today’s era. That is, LiveData in Android app with viewmodel. Now, the question comes up

What is LiveData in Android?

First of all, as the name suggest, LiveData is a data which is not dead, it is living like us.😄 I am just kidding guys. Actually in short, it is the data which automatically updates itself as soon as the data changes. LiveData is an observable data holder class. We can observe a LiveData object  in a viewmodel which gets triggered when the respective value changes and we can bind it with the UI component (like TextView, EditText, etc.). This way, we don’t have to update the UI explicitly every time the value changes.

 

Why use LiveData?

There are tons of advantages we get by using LiveData in android apps. Here are some of them:

No memory Leaks:

LiveData observers are bound to the LifeCycle objects and gets cleaned up when the respective lifecycle is destroyed.

Send events to only active activities:

LiveData send the event updates only to the activities which are active. I.e. user is interacting with them. If the activity is not in running state, then it doesn’t send events avoiding chance of crashes and exceptions.

Data always remains up to date:

If a lifecycle becomes inactive, it receives the latest data upon becoming active again. LiveData provide the latest data to it.

Shall we go now to see how to implement this LiveData in our app? Lets take one simple example to understand the idea.

Android LiveData Example

In this tutorial, we will be using ViewModel class and the livedata in it. We will be creating a simple app in which we are taking two TextViews along with a button. Each button click will increment the counter by one. Lets have a look at the final app we will be building.


 

 

 

Declare dependencies for LiveData in android app

Okay, Lets create a new android project and add the following dependencies in its build.gradle module file as follows:

def lifecycle_version = "2.5.1"
// ViewModel
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
// LiveData
implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"

Setup the UI

Now, we will set up the UI part. we are adding two counter TextViews which starts at 0. One variable is declared in an activity with a traditional approach and another is in ViewModel with a LiveData in our android app. We will observe the counter variable in the viewmodel and update the UI each time the value increments. Lets create this layout in activity_main.xml as follows.

<?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"
    tools:context=".MainActivity"
    android:layout_margin="5dp">

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Android LiveData Tutorial"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:textSize="30sp"
        android:layout_marginTop="8dp"
        android:textStyle="bold"/>

    <TextView
        android:id="@+id/activity_variable_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="32dp"
        android:gravity="center"
        android:text="Activity variable: "
        android:textSize="20sp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/textView" />

    <TextView
        android:id="@+id/activity_counter"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="0"
        app:layout_constraintStart_toEndOf="@+id/activity_variable_title"
        app:layout_constraintTop_toTopOf="@+id/activity_variable_title"
        android:textSize="20sp"/>

    <TextView
        android:id="@+id/livedata_variable_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:text="Livedata variable: "
        android:textSize="20sp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/activity_counter" />

    <TextView
        android:id="@+id/livedata_counter"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="0"
        app:layout_constraintStart_toEndOf="@+id/livedata_variable_title"
        app:layout_constraintTop_toTopOf="@+id/livedata_variable_title"
        android:textSize="20sp"/>

    <Button
        android:id="@+id/increment_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="24dp"
        android:text="Increment"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/livedata_variable_title" />

</androidx.constraintlayout.widget.ConstraintLayout>

Hey, our UI is ready. Now, we are first going to build a ViewModel.

Build the ViewModel for LiveData

At first, lets create a file CounterViewModel.kt as follows. Below it, I will explain what we are doing in this file.

package net.softglobe.livedatatutorial

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

class CounterViewModel : ViewModel() {
    private val _counter = MutableLiveData<Int>()
    var count = 0

    fun getCounter() : LiveData<Int> {
        return _counter
    }

    fun incrementCounter() {
        count++
        _counter.value = count
    }
}

Now, lets understand what we are doing in the above file. We are declaring one private variable _counter which is of type MutableLiveData<Int>. That means, it is an MutableLiveData holding an integer value. The MutableLiveData is actually a class extended from LiveData but with the write access. Along with it, we have declared a simple integer variable counter and two functions to get and increment the value of _counter variable. With the help of incrementCounter() function, incrementing the value of count variable and assigning it to the _counter mutable variable. Then from the getCounter function, we are getting this incremented value.

Code the MainActivity

Finally, lets build the MainActivity.kt to complete the project.

package net.softglobe.livedatatutorial

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import android.widget.TextView
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider

class MainActivity : AppCompatActivity() {
    lateinit var viewmodel : CounterViewModel
    var counter = 0

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

        viewmodel = ViewModelProvider(this).get(CounterViewModel::class.java)
        val livedataTextView = findViewById<TextView>(R.id.livedata_counter)

        findViewById<Button>(R.id.increment_button).setOnClickListener {
            val activityCounter = findViewById<TextView>(R.id.activity_counter)
            counter++
            activityCounter.text = counter.toString()
            viewmodel.incrementCounter()
        }

        viewmodel.getCounter().observe(this, Observer {
            livedataTextView.text = it.toString()
        })
    }
}

Let me explain what we are doing in above file. We are initializing the viewmodel instance and setting the button OnClickListener event handler. We want button to increment both of the counters in TextViews by 1 each time button is pressed. First thing, we are initializing the local variable counter and assigning the value to the first TextView. Also, we are calling the incrementCounter() method in a ViewModel.

Later comes the interesting part. We are calling the method getCounter() form the ViewModel and observing it with the Observer object. Inside it, we are assigning the value we get using the it keyword to the TextView. This observer is called automatically every the _counter variable inside the ViewModel is incremented and it automatically updates the UI for us. This is the real power of using LiveData in android app.

The orientation change magic with ViewModel!

Also, you might have seen in the above app running video that after the screen rotates, the first counter resets to 0 but the second counter does not reset. Why? because every time the screen is rotated, the activity is recreated and thus its instance variables are recreated. But in case of second counter, we are using a variable defined in ViewModel and ViewModel survives the orientation change and the LoveData provides the latest up to date value through its observers. Thus, we see no change in the counter. This is the combined work of ViewModel and LiveData in android app.

That’s it friends! We are done. This is a very short and simple tutorial. I kept it that way to focus on the main concept by reducing complexity as much as possible. Hope that helps you in your programming journey. try to implement it on your own and let me know if you have some doubts.

Download Source Code

Want to jump directly to the implementation? No worries. here is the GitHub repo link of the source code:

Download Source Code

Something extra from me… ☺️

I would like to offer something extra from my side. Would you like to take it? If yes, then here it is. Technopoints has started its official WhatsApp Group where programming enthusiasts interact with each others, solve doubts, and learn together. There you will be in a group of like-minded people who are eager to learn, share knowledge, ask doubts and solve others doubts too. Additionally, there I share some of the rare programming tips related to Android development, the solution to the challenges I faced while making app projects which look my lot of time and I got stuck on it. With those tips, you will avoid common mistakes and conquer the hurdles of your programming journey.

Agree? Great! here is the invite link:

Click here to join the Technopoints WhatsApp Group!

It is open for programmers all over the Globe. Lets connect, share knowledge and grow together. hope to see you in the next tutorial soon with another new hot topic. Thanks, Good bye! 😄

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.