Model-View-Presenter (MVP) ist ein bekanntes Entwurfsmuster für GUI-Anwendungen. Für Android ermöglicht die Implementierung der Geschäftslogik in einem einfachen Java-Modul das Testen ohne einen Android-Emulator zu benötigen.
Ich habe jedoch Schwierigkeiten mit der Implementierung des Musters auf Android, da ich spezielle Anforderungen an die GUI von Android-Anwendungen habe:
Eine Aktivität kann zu irgendeinem Zeitpunkt zerstört werden (eingehender Anruf, Benutzer drückt die Home-Taste, ...), und wenn sie neu erstellt wird, sollte sie sich genau in dem Zustand befinden, in dem sie sich befand. Dies ist anders als bei den meisten anderen GUI-Anwendungen.
Eine Aktivität kann viele Lebenszykluszustände durchlaufen. In diesem Fall kann die Benutzeroberfläche der Aktivität nicht geändert werden. Wenn beispielsweise einige Daten im Hintergrund geladen werden, können sie nicht an den View-Teil von MVP (Activity) übergeben werden, wenn sie sich in einem angehaltenen Zustand befinden. Auch dies ist eine ungewöhnliche Anforderung.
Ich habe den Blogbeitrag MVP für Android gelesen und habe mir die Beispielquellcode . Das Endziel, das ich durch die Verwendung des MVP-Musters erreichen möchte, besteht darin, die gesamte Geschäftslogik mithilfe des Transpilers nach Objective-C zu übersetzen. j2objc , sodass die Geschäftslogik wiederverwendet werden kann, während dieselbe App auf iOS implementiert wird.
Gibt es jemanden, der das MVP-Muster für Android erfolgreich implementiert hat, und in diesem Fall, was fehlt mir?
Ich schlage vor, die MVP-Komponente ohne Einbeziehung von Activity zu implementieren und vielleicht konzeptionell darüber nachzudenken, was bei Android und GWT nützlich wäre. Erstellen Sie die Komponente mithilfe von Test-driven-development mit einer gespiegelten View-Oberfläche und fügen Sie Tests hinzu, bis die Geschäftslogik vollständig implementiert und verifiziert ist. TDD hilft dabei, die API der Komponente schlank zu halten (warum schreibt man Tests für Dinge, die man nicht braucht?), Was die Portierung der Komponente erleichtert.
Die von Ihnen beschriebenen Aktivitätsanforderungen können verallgemeinert werden, um plattformunabhängig zu sein: Die Komponente sollte serialisierbar sein (klein 's', nicht speziell Java-Serialisierung) und muss Ereignisse im Lebenszykluszustand akzeptieren. Auch diese können mithilfe von Mocks für Systemfunktionen vollständig getestet werden. Wenn Sie diesen Schritt ausführen, werden Sie wahrscheinlich feststellen, dass nur wenige der Aktivitätsanforderungen notwendigerweise für Android spezifisch sind und auf anderen Plattformen nützlich sein können. Vermeiden Sie die Erstellung riesiger Service-APIs. Um beispielsweise die Serialisierung zu unterstützen, sind nur Speicher- / Lade-Methoden erforderlich, nicht etwa die Paket-API . Ich habe solche Service-APIs für einen anderen Entwickler auf einem Whiteboard beschrieben, um eine gute Möglichkeit zu finden, unnötigen Fluff zu finden.
Als Nächstes portieren Sie die Komponente für Android, indem Sie beispielsweise eine Aktivität erstellen, die an die Komponente delegiert und Android-spezifische Implementierungsklassen für die mockigen Schnittstellen bereitstellt. Es sollte alles "nur funktionieren" das erste Mal, aber in der Realität, einige Anforderungen wurden möglicherweise verpasst, so fügen Sie sie zum plattformunabhängigen Teil und wiederholen.
Wenn Sie bereit sind, auf iOS zu portieren, implementieren Sie diese zuvor gespotteten Schnittstellen erneut. Wenn diese Schnittstellen mager sind, ist es wahrscheinlich einfacher, sie direkt in Objective-C zu erstellen und die von j2objc erzeugten Protokoll-Header zu importieren. Zum Beispiel implementiert die NSDictionaryMap -Klasse von j2objc java.util.Map mit einer NSDictionary-Implementierung - Sie müssen keine Java-Version schreiben und übersetzen, da Sie nur iOS-APIs verwenden.
Ich finde, dass die MVP-Variante, auf die Android aufgebaut ist, ein Schritt in die richtige Richtung ist, um die Geschäftslogik in einer App zu isolieren. Wenn Sie jedoch eine bessere Trennung von Bedenken und somit eine wiederverwendbare Domain / Geschäftslogik erreichen möchten, empfehle ich die Verwendung des Presenter First Muster (welches Sie im Kommentar kurz selbst erwähnen). Abgesehen von der abnehmenden Kopplung eignet es sich gut für TDD und ermöglicht es Ihnen, alle Ihre Geschäftslogik zu testen.
Ich habe kürzlich ein GitHub Repo mit Presenter First Beispiele für Android gestartet. Aufgrund der Komplexität der Android-Architektur ist es nicht einfach, das Muster zu implementieren. Die Ansichten sind tendenziell "fetter" als das, was in einer normalen Presenter First-App akzeptabel scheint, hauptsächlich aufgrund des Aktivitätslebenszyklus und anderer Seltsamkeiten. Ich habe mein Bestes getan, um die Geschäftslogik von der Plattform zu entkoppeln, aber es gibt definitiv Raum für Verbesserungen. Sie finden die Beispiele unter:
Vielleicht kannst du da ein paar Ideen verwenden? Oder noch besser selbst etwas beitragen.
Tags und Links android mvp android-activity j2objc