Android Jetpack

ViewModel Android Example with Problem Statement

Pinterest LinkedIn Tumblr

Problem Statement

While you are developing professional-level android apps, one of the most common things we need the consider is configuration changes. These configuration changes are Screen Rotations, Keyboard Changes, Language changes and  Enable multi-window windows. Let us understand android ViewModel example.

The Android OS manages the lifecycle of activities, fragment and other UI controllers. Android Framework Is decide when UI controller will re-create or destroy on particular user action. In case the system destroys and re-create any activity and the UI data get lost. For better clarity let’s takes one example.

Let’s assume you have some Activity for showing the score of two players like below figure.

In this picture you show, We have used two buttons such as A and B. On these buttons, we have set onClickListener that will increase counter by one on every click. When this activity run first time and the score of both player will zero. Meanwhile, click players button, the score will increase by one in every click. Now change the orientation of phone, you see score is set 0 again. Now increase counter and again goes to portrait mode then counter is set 0 again. What happens in configuration changes.  

As per activity lifecycle, while configuration changes happen activity has to destroy and recreate with new configuration. As a result of that values created during the running period of activity will destroy. That scenario is very simple one, but this is one major problem when it comes in a large application. Let’s suppose you have to get data about 2000 product from remote list APIs. Every time configuration change happens have to call API and download data again and again. That is consumed a lot of time and resource.

ViewModel

ViewModel is best solution for this problem. it just a class for view. We usually create one view model for one activity. One activity can have many fragment, means two or more fragment can share one ViewModel. View model create in the memory when activity creates, It lives until the activity cleared from the memory.    

So ViewModel can hold value belong to the activity. As this diagram to the Google developer documentation shows from the movement app launches an activity, the activity appears on the screen. Activity has to pass three life cycle state create, start and resume. Activity has to pass onPause,onStop and onDestroy.

ViewModel starts on invoke onCreate methods. Through that time activity can recreate again and again but it instance will live in the memory holding activity data.

Summary of ViewModel

  • Live through the configuration changes- If any configuration changes the data will live in ViewModel
  • No worry about leak memory
  • Data will be always updated – If API is calling data from remote server the data will always update
  • Data will wait for you- If you call any APIs and that time you will rotate the phone and result delivered before activity recreation data will store in ViewModel and wait for the re-creation of activity

ViewModel Android Demo App

Step to Implementation ViewModel

I’m going to show you how to use ViewModel. It’s very easy you have to follow below step

  • Add dependency in build.gradle
  • Create a subclass of ViewModel
  • Expose methods for data such as getInitialCount() and getCurrentCount() for both players.
  • Write code in Activity

1. Add dependency in build.gradle

For implementing ViewModel Android example you have go to file menu and create a new project. open build.gradle and add below line of code

    def lifecycle_version = "1.1.1"
    implementation "android.arch.lifecycle:extensions:$lifecycle_version"
    annotationProcessor "android.arch.lifecycle:compiler:$lifecycle_version"

2. Create a subclass of ViewModel

Now create a new class with named is MainViewModel which extends ViewModel class and expose below methods.

package com.wave.viewmodelexample;
import androidx.lifecycle.ViewModel;
public class MainViewModel extends ViewModel {
    private int clickCountA, clickCountB = 0;
    public int getInitialCountA() {
        return clickCountA;
    }
    public int getInitialCountB() {
        return clickCountB;
    }
    public int getCurrentCountA() {
        clickCountA += 1;
        return clickCountA;
    }
    public int getCurrentCountB() {
        clickCountB += 1;
        return clickCountB;
    }
}

3. Expose Methods

Now open MainActivity and add below line of code

package com.wave.viewmodelexample;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.ViewModelProviders;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    MainViewModel mainViewModel;
    TextView tvScoreA, tvScoreB;
    Button btnPlayerA, btnPlayerB;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
        /**
         * initialized ViewModel
         */
        mainViewModel = ViewModelProviders.of(this).get(MainViewModel.class);
        // set initial counter from view model
        tvScoreA.setText(String.valueOf(mainViewModel.getCurrentCountA()));
        tvScoreB.setText(String.valueOf(mainViewModel.getCurrentCountB()));
    }
    private void initView() {
        // initialized all views here
        tvScoreA = findViewById(R.id.tvScorePlayerA);
        tvScoreB = findViewById(R.id.tvScorePlayerB);
        btnPlayerA = findViewById(R.id.btnPlayerA);
        btnPlayerB = findViewById(R.id.btnPlayerB);
        btnPlayerA.setOnClickListener(this);
        btnPlayerB.setOnClickListener(this);
    }
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btnPlayerA:
                //set current counter from view model
                tvScoreA.setText(String.valueOf(mainViewModel.getCurrentCountA()));
                break;
            case R.id.btnPlayerB:
                //set current counter from view model
                tvScoreB.setText(String.valueOf(mainViewModel.getCurrentCountB()));
                break;
            default:
        }
    }
}

Finally, following all these steps just RUN the project, The output will be as expected, the counter will not reset zero on configuration change, such as here.

This is a basic ViewModel Android example. If you have any queries, feel free to ask them in the comment section below. Read our next article that was written on LiveData. Happy Coding 🙂

4 Comments

  1. To run proper please set getInitialCountA() instead of getCurrentCountA() in oncreate like below.

    tvScoreA.setText(String.valueOf(mainViewModel.getInitialCountA()));
    tvScoreB.setText(String.valueOf(mainViewModel.getInitialCountB()));

    in oncreate then it run proper

  2. on configurational change it’s not retaining its value instead it gets incremented by one eveytime

  3. hey what about getInitialCount method you have not used it anywhere then what’s the purpose of that method inside view Model

    • mrutyunjay senapati

      in Oncreate method you have to call getInitialCount method

Write A Comment