Building Cloud Expertise with centron - Our Tutorials

Whether you are a beginner or an experienced professional, our practical tutorials provide you with the knowledge you need to make the most of our cloud services.

Android MVVM: Dynamically Updating UI with LiveData and Data Binding

In this post, we will use the MVVM architecture in Android, combining LiveData and Data Binding. LiveData makes it easy to automatically update the user interface (UI) as data in the ViewModel changes. We will demonstrate how these technologies work together in a simple login application.

Introduction

MVVM (Model-View-ViewModel) is an architectural pattern frequently used in Android development to ensure a clean separation of layers in an application. The Model handles data logic, while the ViewModel acts as an intermediary between the Model and View. Data Binding and LiveData make working with MVVM particularly efficient by simplifying the code and minimizing potential errors.

What is LiveData?

LiveData is a container that holds data and observes changes to it. The key feature of LiveData is its lifecycle awareness: it only updates the UI when the UI component is active in the foreground. This significantly reduces crashes, as UI updates are no longer executed when the Activity or Fragment has already been destroyed.

Project Structure and Dependencies

To get started with MVVM and LiveData, we need to add the corresponding dependencies to the build.gradle file of our project:

android {
    ...
    dataBinding {
        enabled = true
    }
    ...
}

dependencies {
    ...
    implementation 'android.arch.lifecycle:extensions:1.1.1'
    implementation 'com.android.support:design:28.0.0-beta01'
    ...
}

These dependencies enable us to use Data Binding and LiveData.

Model Layer

The Model is represented by the User class. This class contains the validation logic for the input fields:

public class User {
    private String mEmail;
    private String mPassword;

    public User(String email, String password) {
        mEmail = email;
        mPassword = password;
    }

    public String getEmail() {
        return mEmail == null ? "" : mEmail;
    }

    public String getPassword() {
        return mPassword == null ? "" : mPassword;
    }

    public boolean isEmailValid() {
        return Patterns.EMAIL_ADDRESS.matcher(getEmail()).matches();
    }

    public boolean isPasswordLengthGreaterThan5() {
        return getPassword().length() > 5;
    }
}

Layout with Data Binding

The XML file activity_main.xml provides the user interface and binds the ViewModel:

<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <data>
        <variable
            name="loginViewModel"
            type="com.example.androidmvvm.LoginViewModel" />
    </data>
    <ScrollView android:layout_width="match_parent" android:layout_height="match_parent">
        <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content">
            
            <android.support.design.widget.TextInputLayout android:layout_width="match_parent">
                <EditText android:id="@+id/inEmail" android:layout_width="match_parent"
                    android:hint="Email" android:text="@={loginViewModel.email}" />
            </android.support.design.widget.TextInputLayout>

            
            <android.support.design.widget.TextInputLayout android:layout_width="match_parent">
                <EditText android:id="@+id/inPassword" android:layout_width="match_parent"
                    android:hint="Password" android:text="@={loginViewModel.password}" />
            </android.support.design.widget.TextInputLayout>

            
            <Button android:id="@+id/button" android:layout_width="match_parent"
                android:text="LOGIN" android:onClick="@{()-> loginViewModel.onLoginClicked()}" />

            
            <ProgressBar android:id="@+id/progressBar" style="?android:attr/progressBarStyleLarge"
                android:visibility="@{loginViewModel.busy}" />
        </LinearLayout>
    </ScrollView>
</layout>

ViewModel

In the ViewModel, we implement the logic that interacts with the UI thread:

public class LoginViewModel extends ViewModel {
    public MutableLiveData<String> email = new MutableLiveData<>();
    public MutableLiveData<String> password = new MutableLiveData<>();
    public MutableLiveData<String> errorEmail = new MutableLiveData<>();
    public MutableLiveData<String> errorPassword = new MutableLiveData<>();
    private MutableLiveData<User> userMutableLiveData = new MutableLiveData<>();

    public LiveData<User> getUser() {
        return userMutableLiveData;
    }

    public void onLoginClicked() {
        // Set the ProgressBar to visible
        new Handler().postDelayed(() -> {
            User user = new User(email.getValue(), password.getValue());
            if (!user.isEmailValid()) {
                errorEmail.setValue("Please enter a valid email");
            }
            if (!user.isPasswordLengthGreaterThan5()) {
                errorPassword.setValue("Password must be longer than 5 characters");
            }
            userMutableLiveData.setValue(user);
        }, 3000);
    }
}

MainActivity

In the MainActivity, we observe the changes in LiveData:

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
        LoginViewModel loginViewModel = ViewModelProviders.of(this).get(LoginViewModel.class);
        binding.setLoginViewModel(loginViewModel);
        binding.setLifecycleOwner(this);

        loginViewModel.getUser().observe(this, user -> {
            if (user != null) {
                Toast.makeText(this, "Email: " + user.getEmail(), Toast.LENGTH_SHORT).show();
            }
        });
    }
}

Conclusion

In this post, we demonstrated how to implement MVVM in Android using LiveData and Data Binding. By utilizing these technologies, development becomes simpler and less error-prone due to well-structured and maintainable code.

Get Started with Your Free Trial Today!

Unlock the full potential of Android development with our cloud solutions. Experience seamless integration, powerful tools, and real-time collaboration to elevate your mobile app projects. Start your free trial now and bring your Android apps to life faster and more efficiently with our cutting-edge cloud services.

Try for free!