Einführung in Android-Architekturkomponenten

Android wurde 2005 auf der ganzen Welt eingeführt. In diesen 12 Jahren hat die Plattform erstaunliche Erfolge verzeichnet und ist das am häufigsten installierte mobile Betriebssystem. In dieser Zeit wurden 14 verschiedene Versionen des Betriebssystems eingeführt, wobei Android immer ausgereifter wurde. Ein sehr wichtiger Bereich der Plattform wurde jedoch weiterhin ignoriert: ein Standardarchitekturmuster, das die Plattform-Besonderheiten beherrscht und einfach genug ist, um vom durchschnittlichen Entwickler verstanden und übernommen zu werden.

Nun, besser spät als nie. Bei der letzten Google I / O entschied sich das Android-Team schließlich dafür, dieses Problem anzugehen und auf das Feedback von Entwicklern auf der ganzen Welt zu reagieren, eine offizielle Empfehlung für eine Android-Anwendungsarchitektur anzukündigen und die Bausteine ​​für die Implementierung bereitzustellen: die neue Architektur Komponenten. Und noch besser: Sie haben es geschafft, ohne die Offenheit des Systems, das wir alle kennen und lieben, zu beeinträchtigen.

In diesem Lernprogramm werden wir die standardisierte Architektur untersuchen, die das Android-Team bei Google I / O vorgeschlagen hat, und die wichtigsten Elemente der neuen Architekturkomponenten betrachten: Lebenszyklus, ViewModel, Lebensdaten, und Zimmer. Wir werden dem Code nicht zu viel Aufmerksamkeit schenken, sondern uns auf das Konzept und die Logik hinter diesen Themen konzentrieren. Wir werden auch ein paar einfache Ausschnitte betrachten, die alle mit Kotlin geschrieben wurden, einer erstaunlichen Sprache, die jetzt offiziell von Android unterstützt wird.

1. Was fehlte Android??

Wenn Sie Ihre Reise als Entwickler gerade erst beginnen, wissen Sie möglicherweise nicht genau, worüber ich spreche. Schließlich kann die Anwendungsarchitektur auf den ersten Blick ein obskures Thema sein. Aber glauben Sie mir, Sie werden bald lernen, wie wichtig es ist! Wenn eine Anwendung wächst und komplexer wird, wird ihre Architektur immer wichtiger. Es kann Ihre Arbeit buchstäblich zur Seligkeit oder zur Hölle machen.

Anwendungsarchitektur

Grob gesagt: Eine Anwendungsarchitektur ist ein konsistenter Plan, der vor Beginn des Entwicklungsprozesses erstellt werden muss. Dieser Plan enthält eine Karte, wie die verschiedenen Anwendungskomponenten organisiert und miteinander verbunden werden sollen. Es enthält Richtlinien, die während des Entwicklungsprozesses befolgt werden sollten, und erzwingt einige Opfer (im Allgemeinen mehr Klassen und Boilerplate), die Ihnen am Ende beim Erstellen einer gut geschriebenen Anwendung helfen, die besser testbar, erweiterbar und wartbar ist.

Software-Anwendungsarchitektur ist der Prozess der Definition einer strukturierten Lösung, die alle technischen und betrieblichen Anforderungen erfüllt und gleichzeitig die üblichen Qualitätsmerkmale wie Leistung, Sicherheit und Verwaltbarkeit optimiert. Dies beinhaltet eine Reihe von Entscheidungen, die auf einer Vielzahl von Faktoren basieren, und jede dieser Entscheidungen kann erhebliche Auswirkungen auf die Qualität, Leistung, Wartbarkeit und den Gesamterfolg der Anwendung haben.
- Microsofts Software-Architektur- und Designhandbuch

Eine gute Architektur berücksichtigt viele Faktoren, insbesondere die Systemeigenschaften und -grenzen. Es gibt viele verschiedene architektonische Lösungen, alle mit Vor- und Nachteilen. Einige Schlüsselbegriffe sind jedoch allen Visionen gemeinsam.

Alte Fehler

Bis zur letzten Google I / O hat das Android-System keine spezifische Architektur für die Anwendungsentwicklung empfohlen. Das bedeutet, dass Sie völlig frei waren, jedes Modell auf den Markt zu bringen: MVP, MVC, MVPP oder sogar überhaupt kein Muster. Darüber hinaus bot das Android-Framework nicht einmal native Lösungen für Probleme, die vom System selbst erstellt wurden, insbesondere für den Lebenszyklus der Komponente.

Wenn Sie also ein Model View Presenter-Muster in Ihre Anwendung übernehmen wollten, mussten Sie Ihre eigene Lösung von Grund auf entwickeln, viel Boilerplate-Code schreiben oder eine Bibliothek ohne offizielle Unterstützung verwenden. Durch das Fehlen von Standards wurden viele schlecht geschriebene Anwendungen erstellt, deren Codebasis schwer zu warten und zu testen war. 

Wie gesagt, diese Situation wird seit Jahren kritisiert. In der Tat habe ich vor kurzem über dieses Problem und seine Lösung in meiner Anleitung zum Modellieren von Presenter-Modellen für Android berichtet. Aber das Wichtigste ist, dass das Android-Team nach 12 langen Jahren endlich beschlossen hat, sich unsere Beschwerden anzuhören und uns bei diesem Problem zu helfen.

2. Android-Architektur

Der neue Android-Architekturhandbuch definiert einige Schlüsselprinzipien, denen eine gute Android-Anwendung entsprechen sollte, und schlägt dem Entwickler einen sicheren Pfad zum Erstellen einer guten App vor. Der Leitfaden besagt jedoch ausdrücklich, dass die dargestellte Route nicht obligatorisch ist und letztendlich die Entscheidung persönlich ist. Es ist der Entwickler, der entscheiden sollte, welche Art von Architektur verwendet werden soll.

Laut dem Leitfaden sollte eine gute Android-Anwendung eine solide Trennung der Bedenken bieten und die Benutzeroberfläche von einem Modell ablenken. Code, der keine Interaktion mit einer Benutzeroberfläche oder einem Betriebssystem ausführt, darf nicht in einer Aktivität oder einem Fragment enthalten sein. Wenn Sie sie so sauber wie möglich halten, können Sie viele lebenszyklusbezogene Probleme vermeiden. Schließlich kann das System Aktivitäten oder Fragmente jederzeit zerstören. Die Daten sollten auch mit Modellen behandelt werden, die von der Benutzeroberfläche isoliert sind, und folglich aus Lebenszyklusproblemen.

Die neue empfohlene Architektur

Die von Android empfohlene Architektur lässt sich unter den uns bekannten Standardmustern nicht ohne weiteres kennzeichnen. Es sieht wie ein Model View Controller-Muster aus, ist jedoch so eng mit der Systemarchitektur verbunden, dass es schwierig ist, jedes Element mit den bekannten Konventionen zu kennzeichnen. Dies ist jedoch nicht relevant, da das Wichtigste ist, dass die neuen Architekturkomponenten für die Trennung der Anliegen mit hervorragender Testbarkeit und Wartbarkeit erforderlich sind. Und noch besser ist es einfach zu implementieren.

Um zu verstehen, was das Android-Team vorschlägt, müssen wir alle Elemente der Architekturkomponenten kennen, da diese die Hauptanforderung für uns sind. Es gibt vier Komponenten mit jeweils einer bestimmten Rolle: Zimmer, ViewModel, Lebensdaten, und Lebenszyklus. Alle diese Teile haben ihre eigenen Verantwortlichkeiten und sie arbeiten zusammen, um eine solide Architektur zu schaffen. Schauen wir uns ein vereinfachtes Diagramm der vorgeschlagenen Architektur an, um sie besser zu verstehen.

Wie Sie sehen, haben wir drei Hauptelemente, von denen jedes seine Verantwortung trägt. 

  1. Das Aktivität und Fragment repräsentieren die Aussicht Schicht, die sich nicht mit Geschäftslogik und komplexen Vorgängen befasst. Es konfiguriert nur die Ansicht, handhabt die Benutzerinteraktion und, was am wichtigsten ist, Beobachtungen und Exponate Lebensdaten Elemente aus der ViewModel.
  2. Das ViewModel beobachtet automatisch das Lebenszyklus Status der Ansicht, um die Konsistenz bei Konfigurationsänderungen und anderen Android-Lebenszyklusereignissen zu gewährleisten. Es wird auch von der Ansicht gefordert, Daten aus der Datenbank abzurufen Repository, die als beobachtbar bereitgestellt wird Lebensdaten. Es ist wichtig zu verstehen, dass die ViewModel noch nie verweist auf die Aussicht direkt und dass die Aktualisierungen der Daten immer von der Lebensdaten Entität.
  3. Das Repository ist keine spezielle Android-Komponente. Es ist eine einfache Klasse ohne besondere Implementierung, die dafür verantwortlich ist, Daten aus allen verfügbaren Quellen von einer Datenbank zu Web-Services abzurufen. Es verarbeitet all diese Daten und wandelt sie im Allgemeinen in beobachtbare Daten um Lebensdaten und zur Verfügung zu stellen ViewModel.
  4. Das Zimmer database ist eine SQLite-Zuordnungsbibliothek, die den Umgang mit einer Datenbank erleichtert. Es schreibt automatisch eine Tonne Boilerplate, prüft Fehler zur Kompilierzeit, und am besten kann es Abfragen direkt mit Observable zurückgeben Lebensdaten.

Ich bin mir sicher, dass Sie bemerkt haben, dass wir viel über Observables gesprochen haben. Das Observer Pattern ist eine der Grundlagen des Lebensdaten Element und Lebenszyklus Komponenten bewusst. Dieses Muster ermöglicht es einem Objekt, eine Liste von Beobachtern über Änderungen des Zustands oder der Daten zu benachrichtigen. Wenn also eine Aktivität beobachtet wird a Lebensdaten Entität erhält es Aktualisierungen, wenn diese Daten irgendeine Art von Änderung erfahren.

Eine weitere Android-Empfehlung ist die Konsolidierung der Architektur mit einem Dependency Injection-System, wie Dagger 2 von Google oder mit dem Service Locator-Muster (das viel einfacher ist als DI, jedoch ohne viele Vorteile). DI oder Service Locator werden in diesem Tutorial nicht behandelt, aber Envato Tuts + bietet einige hervorragende Tutorials zu diesen Themen. Beachten Sie jedoch, dass es einige Besonderheiten bei der Arbeit mit Dagger 2 und Android-Komponenten gibt, die im zweiten Teil dieser Serie erläutert werden.

3. Architekturkomponenten

Wir müssen tief in die Aspekte der neuen Komponenten eintauchen, um dieses Architekturmodell wirklich verstehen und anwenden zu können. Wir werden jedoch nicht auf alle Details in diesem Tutorial eingehen. Aufgrund der Komplexität der einzelnen Elemente werden in diesem Lernprogramm nur die Grundgedanken hinter jedem Element beschrieben und einige vereinfachte Codeausschnitte dargestellt. Wir werden versuchen, ausreichend Platz für die Präsentation der Komponenten zu schaffen und Ihnen den Einstieg zu erleichtern. Aber keine Angst, denn zukünftige Artikel in dieser Serie werden tief graben und alle Besonderheiten der Architekturkomponenten abdecken.

Lifecycle-Aware-Komponenten

Mit den meisten Android-App-Komponenten sind Lebenszyklen verknüpft, die direkt vom System selbst verwaltet werden. Bis vor kurzem war es Aufgabe des Entwicklers, den Status der Komponenten zu überwachen und entsprechend zu handeln, um Aufgaben rechtzeitig zu initialisieren und zu beenden. Es war jedoch sehr einfach, sich zu verwirren und Fehler in Bezug auf diese Art von Operation zu machen. Aber die android.arch.lifecycle Paket hat das alles geändert. 

Nun haben Aktivitäten und Fragmente eine Lebenszyklus Objekt, das mit ihnen verbunden ist und durch beobachtet werden kann LifecycleObserver Klassen, wie ein ViewModel oder ein beliebiges Objekt, das diese Schnittstelle implementiert. Dies bedeutet, dass der Beobachter Aktualisierungen über die Zustandsänderungen des beobachteten Objekts erhält, z. B. wenn eine Aktivität angehalten wird oder wann sie gestartet wird. Es kann auch den aktuellen Status des beobachteten Objekts überprüfen. Daher ist es jetzt viel einfacher, Operationen auszuführen, bei denen der Lebenszyklus des Frameworks berücksichtigt werden muss.

Fürs Erste, um eine Aktivität oder Fragment das diesem neuen Standard entspricht, müssen Sie ein erweitern LebenszyklusAktivität oder LebenszyklusFragment. Es ist jedoch möglich, dass dies nicht immer notwendig ist, da das Android-Team diese neuen Tools vollständig in sein Framework integrieren möchte.

Klasse MainActivity: LifecycleActivity () überschreibe fun onCreate (savedInstanceState: Bundle?) super.onCreate (savedInstanceState) setContentView (R.layout.activity_main)

Das LifecycleObserver erhält Lebenszyklus Ereignisse und kann durch Annotation reagieren. Es ist kein Methodenüberschreiben erforderlich.

Klasse MainActivityObserver: LifecycleObserver, AnkoLogger @OnLifecycleEvent (Lifecycle.Event.ON_RESUME) Spaß onResume () info ("onResume") @OnLifecycleEvent (Lifecycle.Event.ON_PAUSE) Spaß onPause (1)

Das Lebensdaten Komponente

Das Lebensdaten Komponente ist ein Datenbehälter, der einen beobachtbaren Wert enthält. Da der Beobachter a Lebenszyklus während der Lebensdaten Instantiation, Lebensdaten wird sich entsprechend verhalten Lebenszyklus Zustand. Wenn der Beobachter  Lebenszyklus Zustand ist GESTARTET oder Wieder aufgenommen, der betrachter ist aktiv; sonst ist es inaktiv

Lebensdaten weiß wann die Daten geändert wurden und ob der Beobachter es ist aktiv und sollte ein Update erhalten. Ein weiteres interessantes Merkmal der Lebensdaten ist, dass es den Beobachter entfernen kann, wenn es sich in einem befindet Lebenszyklus.Zustand.DESTROYED Zustand, um Speicherlecks zu vermeiden, wenn sie von Aktivitäten und Fragmenten beobachtet werden.

EIN Lebensdaten umsetzen müssen onActive und onInactive Methoden.

Klasse LocationLiveData (Kontext: Kontext): LiveData(), AnkoLogger, LocationListener private val locationManager: LocationManager = context.getSystemService (Context.LOCATION_SERVICE) als LocationManager überschreiben fun onActive () info ("onActive") locationManager.requestLocationUpdates (0), 0, 0. überschreiben fun onInactive () info ("onInactive") locationManager.removeUpdates (this) //…

A beobachten Lebensdaten Komponente müssen Sie anrufen Beobachter (LifecycleOwner, Observer).

Klasse MainActivity: LifecycleActivity (), AnkoLogger fun observLocation () val location = LocationLiveData (this) location.observe (this, Observer location -> info ("location: $ location"))

Das ViewModel Komponente

Eine der wichtigsten Klassen der neuen Architekturkomponenten ist die ViewModel, Diese Funktion dient zum Speichern von Daten, die sich auf die Benutzeroberfläche beziehen, und behält ihre Integrität bei Konfigurationsänderungen wie Bildschirmdrehungen bei. Das ViewModel kann mit dem sprechen Repository, bekommen Lebensdaten von ihm und machen es wiederum verfügbar, um von der Ansicht beobachtet zu werden. ViewModel Sie müssen auch keine neuen Anrufe in die Repository nach Konfigurationsänderungen, was den Code stark optimiert.

Um ein Ansichtsmodell zu erstellen, erweitern Sie die ViewModel Klasse.

Klasse MainActivityViewModel: ViewModel () private Varizen: MutableLiveData> = null fun getNotes (): LiveData> if (notes == null) notes = MutableLiveData> () loadNotes () Rückmeldungen !!  private fun loadNotes () // async-Vorgang ausführen, um Notizen abzurufen

Sie können von einer Ansicht aus anrufen ViewProviders.of (Activity | Fragment) .get (ViewModel :: class). Diese Factory-Methode gibt eine neue Instanz von zurück ViewModel oder holen Sie sich die zurückbehaltene, je nachdem. 

Klasse MainActivity: LifecycleActivity (), AnkoLogger override fun onCreate (savedInstanceState: Bundle?) super.onCreate (savedInstanceState) setContentView (R.layout.activity_main) val viewModel = ViewModelProviders.of (this). java) viewModel.getNotes (). observ (this, Observer notes -> info ("notes: $ notes"))

Das Zimmer Komponente

Android unterstützte SQLite von Anfang an; Damit dies funktioniert, war es jedoch immer notwendig, viel Boilerplate zu schreiben. Außerdem hat SQLite keine POJOs (einfache Java-Objekte) gespeichert und keine Abfragen zur Kompilierzeit geprüft. Kommt mit Zimmer um diese Probleme zu lösen! Es ist eine SQLite-Zuordnungsbibliothek, die Java-POJOs beibehalten, Abfragen direkt in Objekte konvertieren, Fehler zur Kompilierzeit prüfen und produzieren kann Lebensdaten Observables aus Abfrageergebnissen. Zimmer ist eine Object Relational Mapping-Bibliothek mit einigen coolen Android-Extras.

Bislang konnte man das meiste tun Zimmer kann andere ORM Android-Bibliotheken verwenden. Keiner von ihnen wird jedoch offiziell unterstützt und kann vor allem nicht produzieren Lebensdaten Ergebnisse. Das Zimmer Bibliothek passt perfekt als persistente Schicht in die vorgeschlagene Android-Architektur.

So erstellen Sie eine Zimmer Datenbank benötigen Sie eine @Entität zu bestehen, das kann ein beliebiger Java-POJO sein, a @Dao Schnittstelle, um Abfragen und Ein- / Ausgabeoperationen durchzuführen, und a @Datenbank abstrakte Klasse, die erweitert werden muss RoomDatabase.

@Entity-Klasse Hinweis @PrimaryKey var id: Long? = null var text: String? = null var date: Long? = null
@Dao-Schnittstelle NoteDAO @Insert (onConflict = OnConflictStrategy.REPLACE) fun insertNote (Hinweis: Hinweis): Long @Update (onConflict = OnConflictStrategy.REPLACE) fun updateNote (Hinweis: Hinweis): Int @Delete fun deleteNote (Hinweis: Hinweis) : Int @Query ("SELECT * FROM note") fun findAllNotes (): LiveData // Bei Kotlin werden die Abfrageargumente // in arg [N] umbenannt, wobei N die Argumentnummer ist. // Bei Java nehmen die Argumente ihren ursprünglichen Namen @Query ("SELECT * FROM note WHERE id =: arg0") an. fun findNoteById (id: Long): LiveData 
@Datenbank (Entitäten = ArrayOf (Anmerkung :: Klasse), Version = 1) Abstrakte Klasse Datenbank: RoomDatabase () Zusammenfassung fun noteDAO (): NoteDAO

Architekturkomponenten zu Ihrem Projekt hinzufügen

Um die neuen Architekturkomponenten zu verwenden, müssen Sie zunächst das Google-Repository zu Ihrem hinzufügen build.gradle Datei. Weitere Informationen finden Sie im offiziellen Leitfaden.

allprojects Repositorys jcenter () // Google Repository-Manager hinzufügen Url 'https://maven.google.com'

Fazit

Wie Sie sehen, umfasst die von Android vorgeschlagene standardisierte Architektur viele Konzepte. Erwarten Sie noch kein umfassendes Verständnis dieses Themas. Schließlich stellen wir nur das Thema vor. Sie haben aber sicherlich schon genug Wissen, um die Logik der Architektur und die Rollen der verschiedenen Architekturkomponenten zu verstehen.

Wir haben über die meisten Themen gesprochen, die sich auf die vorgeschlagene Android-Architektur und ihre Komponenten beziehen. Details zur Komponentenimplementierung und zu einigen Extras wie dem Repository Klasse und das Dagger 2-System können von diesem ersten Teil nicht abgedeckt werden. Wir werden diese Themen in den nächsten Beiträgen untersuchen.

Bis bald!