Android MVVM: Benutzeroberflächen dynamisch mit LiveData und Data Binding aktualisieren

In diesem Beitrag werden wir die MVVM-Architektur in Android verwenden und dabei LiveData und Data Binding kombinieren. LiveData erleichtert es, die Benutzeroberfläche (UI) automatisch zu aktualisieren, sobald sich Daten im ViewModel ändern. Wir zeigen dir, wie diese Technologien in einer einfachen Login-Anwendung zusammenarbeiten.

Einleitung

MVVM (Model-View-ViewModel) ist ein Architekturpattern, das in der Android-Entwicklung häufig genutzt wird, um eine saubere Trennung der Schichten in einer Anwendung zu gewährleisten. Dabei wird das Model für die Datenlogik und das ViewModel als Vermittler zwischen Model und View genutzt. Data Binding und LiveData machen das Arbeiten mit MVVM besonders effizient, da sie den Code vereinfachen und Fehlerquellen minimieren.

Was ist LiveData?

LiveData ist ein Container, der Daten hält und Änderungen daran beobachtet. Das Besondere an LiveData ist seine lebenszyklusbewusste Natur: Es wird nur dann aktualisiert, wenn die UI im Vordergrund aktiv ist. Dies reduziert Abstürze erheblich, da Updates an die UI nicht mehr ausgeführt werden, wenn die Activity oder das Fragment bereits zerstört wurde.

Projektstruktur und Abhängigkeiten

Um mit MVVM und LiveData zu starten, müssen wir zunächst die entsprechenden Abhängigkeiten in die build.gradle-Datei unseres Projekts hinzufügen:

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

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

Diese Abhängigkeiten ermöglichen es uns, Data Binding und LiveData zu nutzen.

Model-Schicht

Das Model wird durch die User-Klasse dargestellt. Diese enthält die Validierungslogik für die Eingabefelder:

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 mit Data Binding

Die XML-Datei activity_main.xml stellt die Benutzeroberfläche bereit und bindet das 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="Passwort" 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

Im ViewModel implementieren wir die Logik, die mit dem UI-Thread interagiert:

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() {
        // Setze die ProgressBar auf sichtbar
        new Handler().postDelayed(() -> {
            User user = new User(email.getValue(), password.getValue());
            if (!user.isEmailValid()) {
                errorEmail.setValue("Bitte eine gültige E-Mail eingeben");
            }
            if (!user.isPasswordLengthGreaterThan5()) {
                errorPassword.setValue("Das Passwort muss länger als 5 Zeichen sein");
            }
            userMutableLiveData.setValue(user);
        }, 3000);
    }
}

MainActivity

In der MainActivity beobachten wir die Änderungen am 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, "E-Mail: " + user.getEmail(), Toast.LENGTH_SHORT).show();
            }
        });
    }
}

Zusammenfassung

In diesem Beitrag haben wir gezeigt, wie MVVM in Android mit LiveData und Data Binding implementiert werden kann. Durch die Verwendung dieser Technologien wird die Entwicklung einfacher und fehlerfreier, da der Code klar strukturiert und gut wartbar ist.

Kostenlosen Account erstellen

Registrieren Sie sich jetzt und erhalten Sie Zugang zu unseren Cloud Produkten.

Das könnte Sie auch interessieren:

centron Managed Cloud Hosting in Deutschland

Mocking Void Methods mit EasyMock

Anleitung, JavaScript
Mocking Void Methods mit EasyMock Im Unit Testing ist Mocking eine essentielle Technik, die Entwicklern ermöglicht, das Verhalten komplexer Objekte zu simulieren. EasyMock ist ein beliebtes Framework zur Erstellung von…