Wie kann man Model View Presenter unter Android übernehmen?
Im vorherigen Tutorial haben wir über das Model View Presenter-Muster gesprochen, wie es auf Android angewendet wird und was seine wichtigsten Vorteile sind. In diesem Tutorial untersuchen wir das Model View Presenter-Muster detaillierter, indem wir es in einer Android-Anwendung implementieren.
Im vorherigen Tutorial haben wir über das Model View Presenter-Muster gesprochen, wie es auf Android angewendet wird und was seine wichtigsten Vorteile sind. In diesem Tutorial untersuchen wir das Model View Presenter-Muster detaillierter, indem wir es in einer Android-Anwendung implementieren.
In diesem Tutorial:
wir erstellen eine einfache Anwendung mit dem MVP-Muster
wir untersuchen, wie das MVP-Muster auf Android implementiert wird
und wir diskutieren, wie einige Schwierigkeiten überwunden werden können, die durch die Android-Architektur verursacht werden
1. Model View Presenter
Das Model View Presenter-Muster ist ein Architekturmuster, das auf dem Model View Controller (MVC)-Muster basiert und die Trennung von Bedenken erhöht und das Testen von Einheiten erleichtert. Es werden drei Layers erstellt: Modell, Ansicht und Präsentator mit jeweils genau definierter Verantwortung.
Das Modell enthält die Geschäftslogik der Anwendung. Es steuert, wie Daten erstellt, gespeichert und geändert werden. Die Ansicht ist eine passive Oberfläche, die Daten anzeigt und Benutzeraktionen an den Präsentator weiterleitet. Der Moderator fungiert als Vermittler. Es ruft Daten aus dem Modell ab und zeigt sie in der Ansicht an. Es verarbeitet auch Benutzeraktionen, die von der Ansicht weitergeleitet werden.
2. Projektplanung und -einrichtung
Wir werden eine einfache Notizenanwendung erstellen, um MVP zu veranschaulichen. Mit der App kann der Benutzer Notizen machen, diese in einer lokalen Datenbank speichern und Notizen löschen. Zur Vereinfachung verfügt die App nur über eine Aktivität.
In diesem Tutorial konzentrieren wir uns hauptsächlich auf die Implementierung des MVP-Musters. Andere Funktionen, wie das Einrichten einer SQLite-Datenbank, das Erstellen eines DAO oder das Behandeln der Benutzerinteraktion, werden übersprungen. Wenn Sie Hilfe zu einem dieser Themen benötigen, bietet Envato Tuts+ einige großartige Tutorials zu diesen Themen.
Aktionsdiagramm und MVP-Layers
Beginnen wir mit der Erstellung einer neuen Notiz. Wenn wir diese Aktion in kleinere Operationen aufteilen, sieht der Ablauf anhand des MVP-Architekturmusters folgendermaßen aus:
Der Benutzer gibt eine Notiz ein und klickt auf die Schaltfläche Notiz hinzufügen.
Der Präsentator erstellt ein Note-Objekt mit dem vom Benutzer eingegebenen Text und fordert das Modell auf, es in die Datenbank einzufügen.
Das Modell fügt die Notiz in die Datenbank ein und informiert den Präsentator darüber, dass sich die Liste der Notizen geändert hat.
Der Präsentator löscht das Textfeld und fordert die Ansicht auf, die Liste zu aktualisieren, um die neu erstellte Notiz anzuzeigen.
MVP-Schnittstellen
Betrachten wir nun die Operationen, die erforderlich sind, um diese Aktion auszuführen, und trennen Sie sie mithilfe von MVP. Um die verschiedenen Objekte locker miteinander zu verbinden, erfolgt die Kommunikation zwischen den Layers über Schnittstellen. Wir brauchen vier Schnittstellen:
RequiredViewOps: Erforderlich Für Presenter verfügbare Ansichtsvorgänge
ProvidedPresenterOps: Vorgänge, die View zur Kommunikation mit Presenter angeboten werden
RequiredPresenterOps: Erforderliche Presenter-Vorgänge, die Model zur Verfügung stehen
ProvidedModelOps: Vorgänge, die Model zur Kommunikation mit Presenter angeboten werden
3. Implementierung von MVP unter Android
Nachdem wir eine Vorstellung davon haben, wie die verschiedenen Methoden organisiert werden sollen, können wir mit der Erstellung unserer App beginnen. Wir vereinfachen die Implementierung, indem wir uns nur auf die Aktion konzentrieren, um eine neue Notiz hinzuzufügen. Die Quelldateien dieses Tutorials sind auf GitHub verfügbar.
Wir verwenden nur eine Activity mit einem Layout, das Folgendes umfasst:
EditText für neue Notizen
Button zum Hinzufügen einer Notiz
RecyclerView, um alle Notizen aufzulisten
zwei TextView-Elemente und eine Button in einem RecyclerView-Halter
Schnittstellen
Beginnen wir mit der Erstellung der Schnittstellen. Um alles organisiert zu halten, platzieren wir die Schnittstellen in einem Halter. Auch in diesem Beispiel konzentrieren wir uns auf die Aktion zum Hinzufügen einer neuen Notiz.
* Operations offered to Model to communicate with Presenter
39
* Handles all data business logic.
40
*/
41
interfaceProvidedModelOps{
42
// Model operations permitted to Presenter
43
intgetNotesCount();
44
NotegetNote(intposition);
45
intinsertNote(Notenote);
46
booleanloadData();
47
}
48
}
View Layer
Jetzt ist es Zeit, die Layers Modell, Ansicht und Präsentator zu erstellen. Da MainActivity als Ansicht fungiert, sollte die RequiredViewOps-Schnittstelle implementiert werden.
Der Moderator ist der Mittelsmann und muss zwei Schnittstellen implementieren:
ProvidedPresenterOps, um Anrufe aus der Ansicht zuzulassen
RequiredPresenterOps, um Ergebnisse vom Modell zu erhalten
Achten Sie besonders auf die Ansichtslayerreferenz. Wir müssen eine WeakReference<MVP_Main.RequiredViewOps> verwenden, da MainActivity jederzeit zerstört werden kann und wir Speicherlecks vermeiden möchten. Außerdem wurde die Modellebene noch nicht eingerichtet. Das machen wir später, wenn wir die MVP-Layers miteinander verbinden.
getView().showToast(makeToast("Cannot add a blank note!"));
137
}catch(NullPointerExceptione){
138
e.printStackTrace();
139
}
140
}
141
}
142
143
/**
144
* Creates a Note object with given text
145
* @param noteText String with Note text
146
* @return A Note object
147
*/
148
publicNotemakeNote(StringnoteText){
149
Notenote=newNote();
150
note.setText(noteText);
151
note.setDate(getDate());
152
returnnote;
153
154
}
155
}
Modell Layer
Die Modell Layer ist für die Verwaltung der Geschäftslogik verantwortlich. Es enthält eine ArrayList mit den zur Datenbank hinzugefügten Notizen, eine DAO-Referenz zum Ausführen von Datenbankoperationen und eine Referenz zum Presenter.
* Gets a specific note from notes list using its array position
44
* @param position Array position
45
* @return Note from list
46
*/
47
@Override
48
publicNotegetNote(intposition){
49
returnmNotes.get(position);
50
}
51
52
/**
53
* Get ArrayList size
54
* @return ArrayList size
55
*/
56
@Override
57
publicintgetNotesCount(){
58
if(mNotes!=null)
59
returnmNotes.size();
60
return0;
61
}
62
}
4. Alles zusammenbinden
Wenn die MVP-Layers vorhanden sind, müssen wir sie instanziieren und die erforderlichen Referenzen einfügen. Bevor wir dies tun, müssen wir einige Probleme ansprechen, die in direktem Zusammenhang mit Android stehen.
Instanziieren der Layers
Da Android die Instanziierung einer Activity nicht zulässt, wird die Ansichtslayer für uns instanziiert. Wir sind für die Instanziierung der Layers Presenter und Model verantwortlich. Leider kann das Instanziieren dieser Layers außerhalb der Activity problematisch sein.
Es wird empfohlen, eine Form der Abhängigkeitsinjektion zu verwenden, um dies zu erreichen. Da unser Ziel darin besteht, uns auf die MVP-Implementierung zu konzentrieren, werden wir einen einfacheren Ansatz verfolgen. Dies ist nicht der beste verfügbare Ansatz, aber am einfachsten zu verstehen. Wir werden später in dieser Serie über MVP und Abhängigkeitsinjektion sprechen.
instanziieren Sie den Präsentator und das Modell in der Aktivität mithilfe lokaler Variablen
richten Sie RequiredViewOps und ProvidedModelOps im Presenter ein
richten Sie RequiredPresenterOps im Modell ein
speichern Sie ProvidedPresenterOps als Referenz für die Ansicht
1
/**
2
* Setup Model View Presenter pattern
3
*/
4
privatevoidsetupMVP(){
5
// Create the Presenter
6
MainPresenterpresenter=newMainPresenter(this);
7
// Create the Model
8
MainModelmodel=newMainModel(presenter);
9
// Set Presenter model
10
presenter.setModel(model);
11
// Set the Presenter as a interface
12
mPresenter=presenter;
13
}
Umgang mit Konfigurationsänderungen
Eine andere Sache, die wir berücksichtigen sollten, ist der Lebenszyklus der Aktivität. Die Activity von Android kann jederzeit zerstört werden, und die Layers Präsentator und Modell können auch damit zerstört werden. Wir müssen dies beheben, indem wir eine Art Zustandsmaschine verwenden, um den Zustand während Konfigurationsänderungen zu speichern. Wir sollten auch die anderen Layers über den Status der Aktivität informieren.
Um dies zu erreichen, verwenden wir eine separate Klasse, StateMaintainer, die ein Fragment enthält, das seinen Status beibehält und dieses Fragment zum Speichern und Abrufen unserer Objekte verwendet. Sie können sich die Implementierung dieser Klasse in den Quelldateien dieses Tutorials ansehen.
Wir müssen dem Präsentator und dem Modell eine onDestroy-Methode hinzufügen, um sie über den aktuellen Status der Aktivität zu informieren. Wir müssen dem Präsentator auch eine setView-Methode hinzufügen, die für den Empfang einer neuen Ansichtsreferenz der neu erstellten Aktivität verantwortlich ist.
Das MVP-Muster kann einige Probleme lösen, die durch die Standardarchitektur von Android verursacht werden. Es macht Ihren Code einfach zu warten und zu testen. Die Einführung von MVP mag zunächst schwierig aussehen, aber sobald Sie die Logik dahinter verstanden haben, ist der gesamte Prozess unkompliziert.
Sie können jetzt Ihre eigene MVP-Bibliothek erstellen oder eine bereits verfügbare Lösung wie Mosby oder simple-mvp verwenden. Sie sollten jetzt besser verstehen, was diese Bibliotheken hinter den Kulissen tun.
Wir sind fast am Ende unserer MVP-Reise. Im dritten und letzten Teil dieser Serie werden wir dem Mix Unit-Tests hinzufügen und unseren Code anpassen, um die Abhängigkeitsinjektion mit Dagger zu verwenden. Ich hoffe Sie dort zu sehen.