Führerschein zum Autofahren oder warum Anwendungen Single-Activity sein sollten

Bild


Auf der AppsConf 2018 , die vom 8. bis 9. Oktober stattfand, hielt ich eine Präsentation über das Erstellen von Android-Anwendungen in einer einzigen Aktivität. Obwohl das Thema bekannt ist, gibt es viele Vorurteile in Bezug auf eine solche Wahl - der überfüllte Raum und die Anzahl der Fragen nach der Rede bestätigen dies. Um nicht auf die Videoaufnahme zu warten, habe ich beschlossen, einen Artikel mit einer Abschrift der Rede zu verfassen.



Was ich erzählen werde


  1. Warum und warum sollte ich zu Einzelaktivität wechseln?
  2. Ein universeller Ansatz zum Lösen von Aufgaben, die Sie gewohnt sind, in mehreren Aktivitäten zu lösen
  3. Beispiele für Standardgeschäftsaufgaben
  4. Engpässe, bei denen Code normalerweise gestützt wird, anstatt alles ehrlich zu tun

Warum ist Einzelaktivität richtig?


Lebenszyklus



Alle Android-Entwickler kennen das Kaltstartschema der Anwendung. Zuerst wird onCreate für die Application-Klasse aufgerufen, dann tritt der Lebenszyklus der ersten Aktivität in Aktion.
Wenn unsere Anwendung mehrere Aktivitäten enthält (und die meisten dieser Anwendungen vorhanden sind), geschieht Folgendes:


App.onCreate() ActivityA.onCreate() ActivityA.onStart() ActivityA.onResume() ActivityA.onPause() ActivityB.onCreate() ActivityB.onStart() ActivityB.onResume() ActivityA.onStop() 

Dies ist das abstrakte Startprotokoll von activityB von ActivityA. Eine leere Zeile ist der Moment, in dem der Start eines neuen Bildschirms aufgerufen wurde. Auf den ersten Blick ist alles in Ordnung. Wenn wir uns jedoch der Dokumentation zuwenden, wird klar: onResume , dass der Bildschirm für den Benutzer sichtbar ist und er mit ihm interagieren kann, ist dies nur nach dem Aufruf von onResume auf jedem Bildschirm möglich:


 App.onCreate() ActivityA.onCreate() ActivityA.onStart() ActivityA.onResume() <-------- ActivityA.onPause() ActivityB.onCreate() ActivityB.onStart() ActivityB.onResume() <-------- ActivityA.onStop() 

Das Problem ist, dass ein solches Protokoll nicht dazu beiträgt, den Lebenszyklus der Anwendung zu verstehen. Wenn der Benutzer noch drinnen ist und wenn er bereits zu einer anderen Anwendung gewechselt oder unsere minimiert hat und so weiter. Dies ist erforderlich, wenn Sie die Geschäftslogik an den LC der Anwendung binden möchten. Halten Sie beispielsweise eine Socket-Verbindung aufrecht, während sich der Benutzer in der Anwendung befindet, und schließen Sie sie beim Beenden


In einer Einzelaktivitätsanwendung ist alles einfach - LC-Aktivität wird zu einer LC-Anwendung. Alles, was Sie für eine Logik benötigen, lässt sich leicht an den Status der Anwendung binden.


Bildschirme starten


Als Benutzer bin ich oft auf die Tatsache gestoßen, dass ein Anruf aus dem Telefonbuch (und dies ist eindeutig der Start einer separaten Aktivität) nach dem Klicken auf einen Kontakt nicht erfolgt. Es ist unklar, womit dies zusammenhängt, aber diejenigen, mit denen ich erfolglos versucht habe, durchzukommen, sagten, sie hätten den Anruf erhalten und das Geräusch von Schritten gehört. Gleichzeitig steckt mein Smartphone schon lange in der Tasche.



Das Problem ist, dass das Starten einer Aktivität ein vollständig asynchroner Prozess ist! Es gibt keine Garantie für einen sofortigen Start, und noch schlimmer, wir können den Prozess nicht kontrollieren. Absolut.


In der Einzelaktivitätsanwendung können wir in Zusammenarbeit mit dem Fragmentmanager den Prozess steuern.
transaction.commit() - wechselt den Bildschirm asynchron, sodass Sie mehrere Bildschirme gleichzeitig öffnen oder schließen können.
transaction.commitNow() - schaltet den Bildschirm synchron um, wenn Sie ihn nicht zum Stapel hinzufügen müssen.
Mit fragmentManager.executePendingTransactions () `können Sie alle zuvor gestarteten Transaktionen jetzt ausführen.


Screen-Stack-Analyse


Stellen Sie sich vor, die Geschäftslogik Ihrer Anwendung hängt von der aktuellen Tiefe des Bildschirmstapels ab (z. B. Verschachtelungsbeschränkungen). Oder Sie müssen am Ende eines Prozesses zu einem bestimmten Bildschirm zurückkehren, und wenn es mehrere identische gibt, zu dem Bildschirm, der der Wurzel am nächsten liegt (dem Beginn der Kette).
Wie bekomme ich einen Aktivitätsstapel? Welche Parameter sollten beim Starten des Bildschirms angegeben werden?



Übrigens über die Magie der Startoptionen für Aktivitäten:


  • Sie können Startflags in Intent angeben (und sie auch miteinander mischen und an verschiedenen Stellen ändern).
  • Sie können dem Manifest Startparameter hinzufügen, da dort alle Aktivitäten beschrieben werden sollten.
  • Fügen Sie hier Absichtsfilter hinzu, um die externe Triggerung zu handhaben.
  • und schließlich an MultiTasks denken, wenn Aktivitäten in verschiedenen "Aufgaben" ausgeführt werden können.

Zusammen führt dies zu Verwirrung und Problemen beim Support-Debugging. Sie können nie mit Sicherheit genau sagen, wie der Bildschirm gestartet wurde und wie er sich auf den Stapel auswirkte.


In einer Einzelaktivitätsanwendung wechseln alle Bildschirme nur über Fragmenttransaktionen. Sie können den aktuellen Stapel von Bildschirmen und gespeicherten Transaktionen analysieren.
In der Cicerone- Bibliotheksdemo können Sie sehen, wie der aktuelle Status des Stapels in der Symbolleiste angezeigt wird.


Bild


Hinweis: In der neuesten Version haben Unterstützungsbibliotheken den Zugriff auf das Fragmentarray im Fragmentmanager blockiert. Wenn Sie dies jedoch wirklich möchten, kann dieses Problem immer behoben werden.


Nur eine Aktivität auf dem Bildschirm


In realen Anwendungen müssen wir auf jeden Fall "logische" Bildschirme in einer Aktivität kombinieren, dann können Sie eine echte Anwendung NUR für Aktivität schreiben. Die Dualität des Ansatzes ist immer schlecht, da das gleiche Problem auf unterschiedliche Weise gelöst werden kann (irgendwo befindet sich das Layout direkt in der Aktivität, und irgendwo ist die Aktivität nur ein Container).


Behalte keine Aktivitäten


Mit diesem Testflag können Sie wirklich einige Fehler in der Anwendung finden, aber das Verhalten, das es reproduziert, tritt NIEMALS in der Realität auf! Es kommt nicht vor, dass der Bewerbungsprozess bestehen bleibt, und in diesem Moment stirbt die Aktivität, obwohl sie nicht aktiv ist! Aktivitäten können nur mit dem Bewerbungsprozess sterben. Wenn die Anwendung dem Benutzer angezeigt wird und das System nicht über genügend Ressourcen verfügt, stirbt alles in der Umgebung (andere inaktive Anwendungen, Dienste und sogar der Starter), und Ihre Anwendung wird bis zum bitteren Ende leben, und wenn sie sterben muss, ist sie vollständig.
Sie können überprüfen.


Vermächtnis


In der Vergangenheit gibt es in Activity eine Menge unnötiger Logik, die für Sie höchstwahrscheinlich nicht nützlich ist. Zum Beispiel alles, was Sie zum Arbeiten mit loaders , actionBar , action menu actionBar benötigen. Dies macht die Klasse selbst ziemlich massiv und schwer.


Animationen


Vielleicht kann jeder eine einfache Schichtanimation erstellen, wenn er zwischen Aktivität wechselt. Hier sollte klargestellt werden, dass Sie einen Rabatt auf die Asynchronität des Aktivitätsstarts gewähren müssen, über den wir bereits gesprochen haben.
Wenn Sie etwas Interessanteres benötigen, können Sie sich an solche Beispiele für Übergangsanimationen erinnern, die in Aktivität erstellt wurden:


Bild


Es gibt jedoch ein großes Problem: Das Anpassen dieser Animation ist fast unmöglich. Es ist unwahrscheinlich, dass dies Designern und Kunden gefällt.


Bei Fragmenten ist alles anders. Wir können direkt auf die Ebene der Hierarchie der Ansicht gehen und jede erdenkliche Animation erstellen! Direkter Beweis hier :


Bild


Wenn Sie sich den Quellcode ansehen, werden Sie feststellen, dass dies in einem normalen Layout erfolgt. Ja, der Code ist dort anständig, aber Animation ist immer schwierig genug, und eine solche Gelegenheit zu haben, ist immer ein Plus. Wenn Sie zwei Aktivitäten gewechselt haben, verfügt die Anwendung nicht über einen gemeinsamen Container, in dem Sie solche Übergänge vornehmen können.


Konfigurieren Sie die On-the-Fly-Konfiguration


Dieser Punkt war nicht in meiner Rede, aber er ist auch sehr wichtig. Wenn Sie über eine Funktion zum Wechseln der Sprache in der Anwendung verfügen, ist die Implementierung bei mehreren Aktivitäten recht problematisch, wenn Sie die Anwendung unter anderem nicht neu starten müssen, sondern an der Stelle bleiben, an der sich der Benutzer zum Zeitpunkt des Aufrufs der Funktionalität befand.


In einer Anwendung mit nur einer Aktivität reicht es aus, das installierte Gebietsschema im Anwendungskontext zu ändern und recreate() für die Aktivität aufzurufen. Der Rest des Systems erledigt alles selbst.


Am Ende


Google verfügt über eine Navigationslösung, in deren Dokumentation ausdrücklich angegeben ist, dass es ratsam ist, Anwendungen für einzelne Aktivitäten zu schreiben.


An dieser Stelle hoffe ich, dass Sie keinen Zweifel daran haben, dass der klassische Ansatz mit mehreren Aktivitäten eine Reihe von Mängeln enthält, die normalerweise ein Auge zudrücken und sich hinter dem allgemeinen Trend der Unzufriedenheit von Android verstecken.


Wenn ja, warum ist Single-Activity dann noch kein Entwicklungsstandard?


Hier werde ich meinen guten Freund zitieren:



Jeder Lead, der ein neues ernstes Projekt startet, hat Angst vor Fehlern und vermeidet riskante Entscheidungen. Das ist richtig. Ich werde jedoch versuchen, einen umfassenden Plan für den Übergang zur Einzelaktivität vorzulegen.


Umschalten auf Einzelaktivität



Wenn Sie diese Anwendung studieren, können Sie anhand der charakteristischen Animationen und Verhaltensweisen feststellen, dass sie für mehrere Aktivitäten geschrieben wurde. Ich könnte mich irren, und alles wurde sogar in benutzerdefinierten Ansichten durchgeführt, aber dies wird unsere Argumentation nicht beeinflussen.


Jetzt Aufmerksamkeit! Wir machen es so:



Wir haben nur zwei Änderungen vorgenommen: Wir haben die AppActivity-Klasse hinzugefügt und alle Aktivitäten durch FlowFragment ersetzt. Betrachten Sie jede Änderung genauer.


Wofür ist AppActivity verantwortlich:


  • enthält nur einen Container für Fragmente
    • ist der Initialisierungspunkt der Scope-UI-Objekte (dies wurde früher in Application durchgeführt, was falsch ist, da beispielsweise Service-Objekte in unserer Anwendung solche Objekte definitiv nicht benötigen).
    • ist ein Anwendungsanbieter
    • bringt alle Vorteile von Single-Activity.

Was ist FlowFragment :


  • macht genau das Gleiche wie die Aktivität, anstelle der sie erstellt wurde.

Neue Navigation


Der Hauptunterschied zum alten Ansatz ist die Navigation.



Zuvor hatte der Entwickler die Wahl: Starten Sie eine neue Aktivität oder eine Fragmenttransaktion in der aktuellen. Die Auswahl ist nicht verschwunden, aber die Methoden haben sich geändert. Jetzt müssen wir entscheiden, ob die Fragmentfragmentierung in AppActivity oder im aktuellen FlowFragment gestartet werden soll.



Ähnliches gilt für die Bearbeitung der Schaltfläche Zurück. Zuvor hat die Aktivität das Ereignis an das aktuelle Fragment übergeben. Wenn sie es nicht verarbeitet hat, hat sie die Entscheidung selbst getroffen. Jetzt übergibt AppActivity das Ereignis an das aktuelle FlowFragment und dieses wiederum an das aktuelle Fragment.


Übertragen von Ergebnissen zwischen Bildschirmen


Für unerfahrene Entwickler ist das Problem der Datenübertragung zwischen Bildschirmen das Hauptproblem des neuen Ansatzes, da früher die Funktion startActivityForResult () verwendet werden konnte!


Nicht im ersten Jahr wurden verschiedene architektonische Ansätze zum Schreiben von Anwendungen diskutiert. Die Hauptaufgabe bleibt gleichzeitig die Trennung von Benutzeroberfläche, Datenschicht und Geschäftslogik. Unter diesem Gesichtspunkt bricht startActivityForResult () den Kanon, da die Daten zwischen den Bildschirmen einer Anwendung auf der Entitätsseite der UI-Ebene übertragen werden. Ich betone, dass es sich nur um eine Anwendung handelt, da wir eine gemeinsame Datenschicht, gemeinsame Modelle in einem globalen Bereich usw. haben. Wir nutzen diese Möglichkeiten nicht und fahren in den Rahmen eines Bundles (Serialisierung, Größe und mehr).
Mein Rat : Verwenden Sie startActivityForResult () nicht in der Anwendung! Verwenden Sie es nur für den vorgesehenen Zweck - um externe Anwendungen auszuführen und Ergebnisse daraus zu erhalten.


Wie starte ich dann einen Bildschirm mit einer Auswahl für einen anderen Bildschirm? Es gibt drei Möglichkeiten:


  1. Zielfragment
  2. Eventbus
  3. Jet-Modell

TargetFragment - eine Option "out of the box", aber die gleiche Datenübertragung auf der Seite der UI-Ebene. Schlechte Option.


EventBus - Wenn Sie sich auf ein Team einigen und - was am wichtigsten ist - die Vereinbarungen steuern können, können Sie die Datenübertragung zwischen Bildschirmen auf dem globalen Datenbus implementieren. Da dies jedoch ein gefährlicher Schritt ist, ist die Schlussfolgerung eine schlechte Option.


Reaktives Modell - Dieser Ansatz impliziert das Vorhandensein von Rückrufen und mehr. Wie Sie sie implementieren, entscheidet das Team jedes Projekts. Dieser Ansatz ist jedoch optimal, da er die Kontrolle über das Geschehen bietet und die Verwendung des Codes für andere Zwecke nicht zulässt. Unsere Wahl!


Zusammenfassung


Ich liebe neue Ansätze, wenn sie einfach sind und offensichtliche Vorteile haben. Ich hoffe, dass dies in diesem Fall der Fall ist. Die Vorteile werden im ersten Teil beschrieben, und Sie sollten die Schwierigkeit beurteilen. Es reicht aus, alle Aktivitäten durch FlowFragment zu ersetzen und die gesamte Logik unverändert zu lassen. Ändern Sie den Navigationscode ein wenig und überlegen Sie, ob Sie mit der Datenübertragung zwischen Bildschirmen arbeiten möchten, falls dies noch nicht geschehen ist.


Um die Einfachheit des Ansatzes zu demonstrieren, habe ich selbst die offene Anwendung auf Single-Activity umgestellt und es dauerte nur ein paar Stunden (natürlich ist es erwähnenswert, dass dies kein altes Erbe ist und alles mehr oder weniger gut mit der Architektur dort ist).


Was ist passiert?


Mal sehen, wie man Standardprobleme in einem neuen Ansatz löst.


BottomNavigationBar und NavigationDrawer


Mit der einfachen Regel, dass wir alle Aktivitäten durch FlowFragment ersetzen, befindet sich das Seitenmenü nun in einem Fragment und wechselt zwischen verschachtelten Fragmenten:



Ähnliches gilt für BottomNavigationBar.
Es ist viel interessanter, dass wir FlowFragment in andere investieren können, da dies immer noch gewöhnliche Fragmente sind!



Diese Option finden Sie in GitFox .


Es ist die Möglichkeit, einfach einige Fragmente in anderen zu kombinieren, wodurch es möglich ist, problemlos eine dynamische Benutzeroberfläche für verschiedene Geräte zu erstellen: Tablets + Smartphones.


DI-Bereiche


Wenn Sie mehrere Produktkäufe auf mehreren Bildschirmen getätigt haben und den Namen des Produkts auf jedem Bildschirm anzeigen müssen, haben Sie es wahrscheinlich bereits in eine separate Aktivität gestellt, in der das Produkt gespeichert und auf den Bildschirmen bereitgestellt wird.
Dies gilt auch für FlowFragment - es enthält eine DI-Skala mit Modellen für alle verschachtelten Bildschirme. Dieser Ansatz eliminiert die komplizierte Steuerung der Lebensdauer des Oszilloskops, indem er an die Lebensdauer des FlowFragments gebunden wird.




Wenn Sie Filter im Manifest verwendet haben, um einen bestimmten Bildschirm im Deep Link zu starten, haben Sie möglicherweise Probleme beim Starten der Aktivität, über die ich im ersten Teil geschrieben habe. Bei dem neuen Ansatz fallen alle Deep-Links in AppActivity.onNewIntent. Ferner gibt es gemäß den erhaltenen Daten einen Übergang zum erforderlichen Bildschirm (oder zu einer Kette von Bildschirmen. Ich schlage vor, diese Funktionalität in Chicheron zu betrachten ).



Prozess Tod


Wenn die Anwendung für mehrere Aktivitäten geschrieben wurde, sollten Sie wissen, dass sich der Benutzer beim Stoppen der Anwendung und beim Wiederherstellen des Prozesses in der letzten Aktivität befindet und alle vorherigen Aktivitäten erst wiederhergestellt werden, wenn sie an sie zurückgegeben werden.



Wenn Sie dies nicht im Voraus berücksichtigen, können Probleme auftreten. Wenn beispielsweise der Bereich, der für die letzte Aktivität benötigt wurde, für die vorherige geöffnet wurde, wird er von niemandem neu erstellt. Was zu tun ist? Dies in die Anwendungsklasse bringen? Öffnen mehrere Punkte Bereiche?


Bei Fragmenten ist alles einfacher, da sie sich in einer Aktivität oder einem anderen FlowFragment befinden und jeder Container wiederhergestellt wird, bevor das Fragment neu erstellt wird.



Wir können andere praktische Aufgaben in den Kommentaren diskutieren, da sonst die Möglichkeit besteht, dass sich der Artikel als zu umfangreich herausstellt.


Und jetzt der interessanteste Teil.


Engpässe (Sie müssen sich erinnern und nachdenken).


Hier sind wichtige Dinge zusammengefasst, über die Sie in jedem Projekt nachdenken sollten, aber jeder ist es so gewohnt, sie in Projekten für mehrere Aktivitäten zu „zerreißen“, dass es sich lohnt, sich daran zu erinnern und zu erklären, wie man sie im neuen Ansatz richtig löst. Und zuerst auf der Liste


Bildschirmdrehung


Das ist die schrecklichste Geschichte für jammernde Fans, dass Android die Aktivität neu erstellt, wenn der Bildschirm gedreht wird. Die beliebteste Lösungsmethode ist die Korrektur der Hochformatausrichtung. Darüber hinaus wird dieser Vorschlag nicht mehr von Entwicklern gemacht, sondern von Managern, die sich vor Redewendungen wie "Die Aufrechterhaltung einer Runde ist sehr schwierig und kostet ein Vielfaches mehr " fürchten .
Wir werden nicht über die Richtigkeit einer solchen Entscheidung streiten. Eine andere Sache ist wichtig: Das Fixieren der Rotation ist nicht vom Tod der Aktivität befreit! Da die gleichen Prozesse bei vielen anderen Ereignissen auftreten: Split-Modus, wenn mehrere Anwendungen auf dem Bildschirm angezeigt werden, Anschließen eines externen Monitors, Ändern der Anwendungskonfiguration im laufenden Betrieb usw.


Darüber hinaus können Sie durch Drehen des Bildschirms die korrekte "Gummiigkeit" des Layouts überprüfen, sodass wir in unserem Team in St. Petersburg die Drehung nicht in allen Verkaufsbaugruppen deaktivieren, auch wenn sie nicht in der Release-Version enthalten ist. Ganz zu schweigen von den typischen Fehlern, die bei der Überprüfung weiterhin auftreten.


Es wurden bereits viele Lösungen für das Drehen geschrieben, angefangen bei Moxy bis hin zu verschiedenen MVVM-Implementierungen. Mach es nicht schwerer als alles andere.


Betrachten Sie einen anderen interessanten Fall.
Stellen Sie sich eine Produktkataloganwendung vor. Wir machen das in Einzelaktivität. Überall ist der Hochformatmodus festgelegt, aber der Kunde möchte eine Funktion, wenn der Benutzer sie beim Anzeigen der Fotogalerie im Querformat betrachten kann. Wie kann man das unterstützen?


Jemand wird die erste Krücke anbieten:


 <activity android:name=".AppActivity" android:configChanges="orientation" /> 

 override fun onConfigurationChanged(newConfig: Configuration?) { if (newConfig?.orientation == Configuration.ORIENTATION_LANDSCAPE) { //ignore } else { super.onConfigurationChanged(newConfig) } } 

Daher können wir super.onConfigurationChanged(newConfig) nicht aufrufen, sondern selbst verarbeiten und nur die erforderliche Ansicht auf dem Bildschirm drehen.
Mit API 23 stürzt das Projekt jedoch mit einer SuperNotCalledException , was eine schlechte Wahl ist .


Die obigen Aussagen haben einen Fehler gemacht:
Ich wurde in den Kommentaren einigermaßen korrigiert, dass das Hinzufügen von android: configChanges = "Orientierung | Bildschirmgröße" ausreicht, und dann können Sie Super aufrufen und Aktivität wird beim Drehen nicht neu erstellt. Es ist nützlich, es zu verwenden, wenn sich WebView oder Map auf dem Bildschirm befindet. Die Initialisierung dauert lange, und Sie möchten dies vermeiden.
Dies hilft, den beschriebenen Fall mit der Galerie zu lösen, aber die Hauptbotschaft dieses Abschnitts: Ignorieren Sie nicht die Neuerstellung der Aktivität , dies kann in vielen anderen Fällen passieren.


Jemand könnte eine andere Lösung vorschlagen:


 <activity android:name=".AppActivity" android:screenOrientation="portrait" /> <activity android:name=".RotateActivity" /> 

Auf diese Weise entfernen wir uns jedoch vom Single-Activity-Ansatz, um ein einfaches Problem zu lösen und uns aller Vorteile des Ansatzes zu entziehen. Dies ist eine Krücke, und eine Krücke ist immer eine schlechte Wahl .


Hier ist die richtige Lösung:


 <activity android:name=".AppActivity" android:configChanges="orientation" /> 

 override fun onResume() { super.onResume() activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR } override fun onPause() { super.onPause() activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT } 

Das heißt, wenn das Fragment geöffnet wird, beginnt sich die Anwendung zu „drehen“, und wenn es zurückkehrt, wird es wieder repariert. Nach meiner Erfahrung funktioniert die AirBnB- App so. Wenn Sie eine Ansicht von Gehäusefotos öffnen, ist die Abbiegungsverarbeitung aktiviert. Im Querformat können Sie das Foto jedoch nach unten ziehen, um die Galerie zu verlassen. Darunter wird der vorherige Bildschirm im Querformat angezeigt, was Sie normalerweise nicht finden, da der Bildschirm unmittelbar nach dem Verlassen der Galerie in ein Hochformat umgewandelt und fixiert wird.



Hier hilft die rechtzeitige Vorbereitung auf Bildschirmumdrehungen.


Transparente Statusleiste


Nur Aktivität kann mit der Systemleiste arbeiten, aber jetzt haben wir nur eine, daher sollten Sie immer angeben


 <item name="android:windowTranslucentStatus">true</item> 

Auf einigen Bildschirmen muss jedoch nicht darunter "gecrawlt" werden, und Sie müssen den gesamten folgenden Inhalt anzeigen. Die Flagge kommt zur Rettung


 android:fitsSystemWindows="true" 

Dies gibt das Layout an, das Sie nicht unter der Systemleiste zeichnen sollten. Wenn Sie es jedoch im Layout des Fragments angeben und dann versuchen, das Fragment über die Transaktion im Fragmentmanager anzuzeigen, werden Sie enttäuscht sein ... es wird nicht funktionieren!
Die Antwort ist schnell Google
Ich empfehle Ihnen dringend, sich mit einer wirklich umfassenden Antwort und vielen nützlichen Links vertraut zu machen.
Eine schnelle und funktionierende ( aber nicht die richtige ) Lösung besteht darin, das Layout in CoordinatorLayout zu verpacken


 <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true"> </android.support.design.widget.CoordinatorLayout> 

Eine bessere Lösung hilft auch bei der Verarbeitung der Tastatur.


Ändern Sie das Layout, wenn die Tastatur angezeigt wird


Wenn die Tastatur verlassen wird, sollte sich das Layout ändern, damit wichtige Elemente der Benutzeroberfläche nicht unerreichbar bleiben. Und wenn wir früher verschiedene Reaktionsmodi für die Tastatur für verschiedene Aktivitäten festlegen konnten, müssen wir dies jetzt in Einzelaktivität tun. Daher ist es notwendig zu verwenden


 android:windowSoftInputMode="adjustResize" 

Wenn Sie den Ansatz aus dem vorherigen Abschnitt verwenden, um eine transparente Statusleiste zu verarbeiten, werden Sie einen unglücklichen Fehler finden: Wenn ein Fragment erfolgreich unter die Statusleiste gecrawlt wurde, wird es beim Anzeigen der Tastatur oben und unten verkleinert, während die Statusleiste und die Tastatur im System funktionieren SystemWindows .


Achten Sie auf den Titel



Was zu tun ist? Lesen Sie die Dokumentation!Und stellen Sie sicher, dass Chris Banes über WindowInsets spricht .


Die Verwendung von WindowInsets ermöglicht


  • Finden Sie die richtige Höhe des Balkenstatus heraus (und nicht den 51-dp-Hardcode).
  • Bereiten Sie die Anwendung für Ausschnitte auf den Bildschirmen neuer Smartphones vor
  • Finde die Höhe der Tastatur heraus (es ist echt!)
  • Empfangen Sie Ereignisse und reagieren Sie auf das Erscheinungsbild der Tastatur.

Jeder lernt WindowInsets!


Begrüßungsbildschirm


Wenn jemand anderes nicht Bescheid weiß, ist der kanonische Begrüßungsbildschirm nicht der erste Bildschirm in der Anwendung, der Daten lädt, sondern das, was der Benutzer beim Start sieht, bis der Aktivitätsinhalt Zeit zum Rendern hat. Es gibt viele Artikel zu diesem Thema.



, Single-Activity, Splash screen. , deep-link Splash screen .



, , , .


, . Single-Activity. - , , .
...
Intent, , ...
Was weiter? :


  • , «». «», . , !
  • , …

, . ? — «» «» .


Was zu tun ist? , .


Activity!
, : , — .
— , ( Activity), .


Activity — . Activity, . .



Fazit


() , Activity, Android-. , .


: Google . — , , Activity .


, , , ! Vielen Dank!

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


All Articles