Android MVVM architecture

In modern Android development, maintaining a clear, testable, and modular code base has become crucial. The architectural practice recommended by Google is to use the MVVM (Model-View-ViewModel) pattern, which is the embodiment of responsive programming ideas in Android application development. In this article, we will delve into the MVVM architecture and demonstrate how to implement it in an Android application through a simple example.

MVVM architecture overview

The MVVM architecture is divided into three core components:

  • Model  – represents the application’s data and business logic, such as network requests, database interactions, etc.
  • View  – Represents the UI components of the application, such as Activities and Fragments.
  • ViewModel  – Acts as an intermediary between View and Model. It processes the data obtained from the Model, making it suitable for View display, and also responds to the View’s user interaction.

Here are the responsibilities of each component:

Model

The Model contains the data processing portion of the application. Typically, a Model can be further divided into several parts:

  • Repository : An API that provides data, which determines whether to obtain data from a local database or the network.
  • Local Data Source : Such as SQLite database or Room.
  • Remote Data Source : Such as Retrofit or other network request libraries.

View

View is the screen that the user sees and interacts with. In Android, it usually refers to  Activity or  Fragment. View is only responsible for displaying data and notifying ViewModel of user operations. It should be as “dumb” as possible and not contain any business logic.

ViewModel

ViewModel is the data provider of the UI. It does not request data directly, but manages data through Repository. ViewModel does not directly reference View, it notifies UI data changes through LiveData or other observer patterns.

Implement MVVM architecture

Let’s understand the implementation of MVVM by building a simple user list interface. We will use the following Jetpack components:

  • LiveData
  • ViewModel
  • View Binding

Step 1: Configure dependencies

First, add the following dependencies to your  build.gradle (Module: app) file:

dependencies {
    // ViewModel 和 LiveData
    implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1"
    implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1"
    
    // View Binding
    buildFeatures {
        viewBinding true
    }
}

Step 2: Create Model

// User.java
public class User {
    private int id;
    private String name;

    public User(int id, String name) {
        this.id = id;
        this.name = name;
    }

    // Getters and setters
    public int getId() {
        return id;
    }

    public String getName() {
        return name;
    }
}

Step 3: Create ViewModel

// MainViewModel.java
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;

import java.util.Arrays;
import java.util.List;

public class MainViewModel extends ViewModel {
    private MutableLiveData<List<User>> users = new MutableLiveData<>();

    public MainViewModel() {
        loadUsers();
    }

    public MutableLiveData<List<User>> getUsers() {
        return users;
    }

    private void loadUsers() {
        // 
        List<User> dummyUsers = Arrays.asList(new User(1, "Alice"), new User(2, "Bob"));
        users.setValue(dummyUsers);
    }
}

Step 4: Create View

exist  activity_main.xml:

<!-- activity_main.xml -->
<LinearLayout ...>
    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</LinearLayout>

MainActivity.kt Use View Binding and ViewModel in : 

// MainActivity.kt
package com.example.myapp;

import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.ViewModelProvider;
import com.example.myapp.databinding.ActivityMainBinding;

public class MainActivity extends AppCompatActivity {

    private MainViewModel mainViewModel;
    private ActivityMainBinding binding;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        //  View Binding
        binding = ActivityMainBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());

        //  ViewModel
        mainViewModel = new ViewModelProvider(this).get(MainViewModel.class);

        //  ViewModel 
        mainViewModel.getUsers().observe(this, users -> {
            // 更新 UI
            StringBuilder userInfo = new StringBuilder();
            for (User user : users) {
                userInfo.append(user.getName()).append("\n");
            }
            binding.textView.setText(userInfo.toString());
        });
    }
}

Remember, LiveData the observation mode ensures that UI components are only updated when  Activity or  Fragment is active.

Step 5: Test your app

Now you can run your application and see  TextView the list of users displayed. This example is very basic, but it shows how to pass data from the ViewModel to the View without requiring the View to know the complexity of the data source.

in conclusion

MVVM is a powerful and flexible architectural pattern that promotes code separation and modularization. By leveraging LiveData and ViewModel, we can create reactive applications that handle lifecycle events and data management gracefully. In addition, the use of View Binding further simplifies the UI code, allowing us to avoid  findViewById cumbersomeness and reduce the chance of errors.

In actual development, you may also need to introduce other Jetpack components such as Data Binding, Room, and Navigation to further improve the efficiency and functionality of the application architecture.

I hope this blog can help you understand and start using the MVVM architecture to build your Android applications.

Leave a Reply

Your email address will not be published. Required fields are marked *