Navigation in der Android-Anwendung

Einführung


Bei der Android-Entwicklung verwenden wir verschiedene Architekturlösungen (Muster). Zum Beispiel Mvp , Mvvm , Mvi usw. ... Jedes dieser Muster löst mehrere wichtige Probleme, und da sie nicht perfekt sind, hinterlassen sie einige ungelöste Probleme. Zu diesen Aufgaben gehören beispielsweise das Navigieren innerhalb der Anwendung (Routing), das Übertragen von Informationen von Bildschirm zu Bildschirm (Sprechen auf dem Bildschirm, ich meine Aktivität, Fragment oder Ansicht) und das Speichern des Anwendungsstatus beim Ändern der Konfiguration (Konfigurationsänderung).


In unserem Unternehmen waren wir auch mit diesen Problemen konfrontiert, einige wurden auf einfache Weise gelöst, aber der erste fand keine spezifische Lösung. Nachdem wir verschiedene Methoden zur Lösung ausprobiert hatten , schrieben wir unsere eigene Flowzard- Bibliothek.


Herausforderung


In unserem Unternehmen verwenden wir Mvp- Architektur. Um maximale Flexibilität beim Anzeigen, Ändern und Übertragen von Daten zwischen Bildschirmen zu gewährleisten, versuchen wir, dem Prinzip der Einzelverantwortung zu folgen. Das Prinzip besagt, dass jedes Modul ein bestimmtes Problem lösen muss. In unserem Fall sollte der Bildschirm von der globalen Aufgabe isoliert sein und die spezifische Aufgabe des Anzeigens / Empfangens von Informationen lösen. Er sollte überhaupt nichts über andere Bildschirme wissen. So können wir maximale Flexibilität erreichen. Unten finden Sie ein Beispiel für die Einrichtung und Verwendung der Bibliothek.


Flowzard


Flow erstellen


class MainFlow(flowManager: FlowManager) : Flow(flowManager) { //      flow override fun onCreate(savedInstance: DataBunch?, data: DataBunch?) { super.onCreate(savedInstance, data) } } 

Flow Navigator erstellen


Navigatoren führen zwei Funktionen aus: Erstellen von Flusscontainern (Aktivität, Fragment, Ansicht) für Übergänge zwischen Fluss und Bildschirme für Übergänge innerhalb des Flusses.


 class DefaultFlowNavigator(activity: AppCompatActivity) : SimpleFlowNavigator(activity){ //    flow  Activity override fun getActivityIntent(id: String, data: Any?): Intent { return when (id) { Flows.SIGN_UP -> Intent(activity, SignupActivity::class.java) else -> throw RuntimeException("Cannot find activity for id=$id") } } } 

An Aktivität ausrichten


Um Aktivität mit Flow zu verknüpfen, erben wir FlowActivity und stellen Navigator bereit, in unserem Fall DefaultFlowNavigator.


 class MainActivity : FlowActivity() { override val navigator: Navigator get() = DefaultFlowNavigator(this) } 

Erstellen Sie den FlowManager


 class DefaultFlowManager : FlowManager() { //    (main) flow override fun createMainFlow(): Flow { return MainFlow(this) } //    flow override fun createFlow(id: String): Flow { return when (id) { Flows.SIGN_UP -> SignupFlow(this) else -> throw RuntimeException("Cannot find flow for id=$id") } } } //   FlowManager  Application class App : Application(), FlowManagerProvider { private val flowManager = DefaultFlowManager() override fun getProvideManager(): FlowManager { return flowManager } } 

Nachrichten zwischen Ablauf und Bildschirm


Wenn Sie auf die Anmeldeschaltfläche klicken, sendet die Aktivität eine Nachricht an den Hauptfluss. Flow erstellt einen SIGN_UP-Flow und wartet auf eine Antwort davon. Wenn die Anmeldung erfolgreich ist, sendet der SIGN_UP-Fluss das Ergebnis an den Hauptfluss und onFlowResult: MainFlow wird mit dem Code und dem Ergebnisobjekt aufgerufen. Der Hauptfluss prüft, ob das Ergebnis korrekt ist, und sendet dann eine Nachricht an die Aktivierung zurück, dass sich der Benutzer erfolgreich angemeldet hat.


 class MainFlow(flowManager: FlowManager) : Flow(flowManager) { companion object { const val LOGIN_REQUEST_CODE = 1 } //     override fun onMessage(code: String, message: Any) { super.onMessage(code, message) if (code == "main" && message == "login") { newFlow(Flows.SIGN_UP, LOGIN_REQUEST_CODE) } } //       flow override fun onFlowResult(requestCode: Int, result: Result) { super.onFlowResult(requestCode, result) if (requestCode == LOGIN_REQUEST_CODE && result is Result.SUCCESS) { sendMessageFromFlow("main", true) } } } class MainActivity : FlowActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) loginButton.setOnClickListener { //   “login”   “main” flow.sendMessage("main", "login") } //     “main” setMessageListener("main") { if (it is Boolean && it) { statusTextView.text = "Logined" } } } } 

Speichern des Status beim Ändern einer Konfiguration oder wenn ein Prozess das Betriebssystem stoppt


Da Android die Aktivitäts- und Fragmentstapel speichert, speichern die mit diesen Containern erstellten Flows ihren Status und stellen ihn wieder her. Mit dem View-Container müssen Sie Ihren benutzerdefinierten FlowManager schreiben, da die Bibliothek noch keinen solchen Manager hat. Im nächsten Update wird es eine Funktion zum Speichern von Zwischendaten aus dem Datenfluss geben.


Da ich nicht viel Code in dem Artikel haben wollte, werde ich mich auf dieses Beispiel beschränken. Hier ist ein Link zum Repository für eine detaillierte Untersuchung der Bibliothek.

Source: https://habr.com/ru/post/de435248/


All Articles