Android Kotlin Fundamentals 04.1: Lebenszyklus und Logging

Dieses Codelab ist Teil des Android Kotlin Fundamentals-Kurss. Sie profitieren von diesem Kurs, wenn Sie nacheinander die Codelabs durcharbeiten. Alle Kurs-Codelabs finden Sie auf der Landingpage für Kotlin-Grundlagen für Android-Entwickler.

Einführung

In diesem Codelab lernst du einen grundlegenden Teil von Android kennen: den Aktivitäts- und Fragmentlebenszyklus. Der Aktivitätslebenszyklus ist die Gruppe von Status, in denen sich eine Aktivität während ihrer Lifetime befinden kann. Der Lebenszyklus reicht von dem Zeitpunkt, zu dem die Aktivität erstellt wird, bis zum Löschen dieser Aktivität. Das System beansprucht dann die Ressourcen dieser Aktivität. Wenn ein Nutzer zwischen den Aktivitäten in Ihrer App und zurück und in Ihre App wechselt, wechseln diese Aktivitäten zwischen verschiedenen Status im Aktivitätslebenszyklus.

Der Lebenszyklus eines Fragments ist dem von Aktivitäten sehr ähnlich. Dieses Codelab konzentriert sich hauptsächlich auf Aktivitäten mit einem schnellen Überblick über Fragmente zum Ende.

Als Android-Entwickler müssen Sie den Aktivitätslebenszyklus verstehen. Wenn Ihre Aktivitäten nicht wie vorgesehen auf den Lebenszyklusstatus reagieren, kann es passieren, dass Ihre App seltsame Fehler erzeugt, Nutzer verwirrt oder zu viele Android-Systemressourcen verwendet. Nur wenn Sie ein gutes Android-Gerät entwickeln, können Sie den Lebenszyklus von Android verstehen und richtig auf Veränderungen im Lebenszyklus reagieren.

Wichtige Informationen

  • Was ist eine Aktivität und wie wird sie in Ihrer App erstellt?
  • Was die onCreate()-Methode der Aktivität bewirkt und welche Art von Vorgängen, die bei dieser Methode ausgeführt werden.
  • Wie Sie XML-Layouts für Ihre Aktivität erstellen und wie Sie ein Layout zur Laufzeit aktualisieren

Lerninhalte

  • Informationen zum Drucken von Logging-Informationen an die Logcat (auch Android-Konsole oder Android-Monitor genannt).
  • Die Grundlagen des Activity- und Fragment-Lebenszyklus und die Callbacks, die aufgerufen werden, wenn die Aktivität zwischen den Status wechselt.
  • Lebenszyklus-Callback-Methoden überschreiben, um Vorgänge zu verschiedenen Zeiten im Aktivitätslebenszyklus auszuführen.
  • Wie Sie die Timber-Bibliothek für die Anmeldung in Ihrer App verwenden

Vorgehensweise

  • Ändern Sie eine Starter-App namens DessertClicker, um Logging-Informationen hinzuzufügen, die im Logcat angezeigt werden.
  • Lebenszyklus-Callback-Methoden überschreiben und Änderungen am Aktivitätsstatus protokollieren.
  • Führen Sie die App aus und notieren Sie sich die Logging-Informationen, die angezeigt werden, wenn die Aktivität gestartet, beendet und fortgesetzt wird.
  • Ändere die App, um die Timber-Bibliothek zu verwenden.
  • Fügen Sie der AndroidTrivia-App Logging hinzu und behalten Sie Änderungen der Fragmentstatus im Blick.

In diesem Codelab arbeiten Sie mit einer Start-App namens DessertClicker. In dieser App erscheint jedes Mal, wenn der Nutzer auf dem Bildschirm auf ein Dessert tippt, die App mit dem Inhalt des Desserts für den Nutzer. Im Layout der App werden die Werte für die Anzahl der Desserts, die gekauft wurden, und für den Gesamtbetrag, den der Nutzer ausgegeben hat, aktualisiert.

Diese App enthält mehrere Fehler im Zusammenhang mit dem Android-Lebenszyklus: In bestimmten Fällen setzt die App die Dessertwerte auf 0 zurück und die App verwendet weiterhin Systemressourcen, auch wenn sie im Hintergrund ausgeführt wird. Wenn du den Android-Lebenszyklus verstehst, kannst du besser verstehen, warum diese Probleme auftreten und wie du sie beheben kannst.

Jede Aktivität und jedes Fragment hat einen sogenannten Lebenszyklus. Dies ist eine Anspielung auf den Lebenszyklus von Tieren, beispielsweise auf den Lebenszyklus dieses Schmetterlings. Die verschiedenen Schmetterlingsarten zeigen ihren Wachstum von der Geburt bis zum vollständigen Entstehen und bis zum Tod.

Ebenso besteht der Aktivitätslebenszyklus aus den verschiedenen Status, die eine Aktivität durchlaufen kann – von der ersten Initialisierung der Aktivität bis hin zum letzten Löschen und der erneuten Arbeitsspeicherreaktion durch das System. Sobald der Nutzer Ihre App startet, zwischen Apps wechselt und innerhalb und außerhalb der App wechselt, ändert sich der Status der Aktivität. Das folgende Diagramm zeigt den gesamten Lebenszyklus der Aktivitäten. Wie die Namen zeigen, geben diese Status den Status der Aktivität an.

Häufig möchten Sie ein bestimmtes Verhalten ändern oder Code ausführen, wenn sich der Status des Aktivitätslebenszyklus ändert. Daher implementieren die Activity-Klasse selbst und alle abgeleiteten Klassen von Activity wie AppCompatActivity eine Gruppe von Lebenszyklus-Callback-Methoden. Android ruft diese Callbacks auf, wenn eine Aktivität von einem Status in einen anderen wechselt. Sie können diese Methoden dann in Ihren eigenen Aktivitäten überschreiben, um Aufgaben als Reaktion auf diese Änderungen des Lebenszyklusstatus auszuführen. Das folgende Diagramm zeigt den Lebenszyklusstatus sowie die verfügbaren überschreibbaren Callbacks.

Außerdem hat ein Fragment einen Lebenszyklus. Der Lebenszyklus eines Fragments ähnelt einem Lebenszyklus einer Aktivität. Deshalb gilt eine Menge des Gelernten für beides. In diesem Codelab konzentrierst du dich auf den Aktivitätslebenszyklus, da es ein wesentlicher Bestandteil von Android ist und am einfachsten in einer einfachen App zu beobachten ist. Hier ist das entsprechende Diagramm für den Fragmentlebenszyklus:

Es ist wichtig zu wissen, wann diese Callbacks aufgerufen werden und was die jeweiligen Callback-Methode ist. Beide Diagramme sind jedoch komplex und können verwirrend sein. In diesem Codelab lernen Sie nicht nur, was der jeweilige Status und Rückruf bedeutet, sondern führen einige Detektivarbeit durch und verstehen Ihre Kenntnisse.

Schritt 1: Methode „onCreate()“ prüfen und Protokollierung hinzufügen

Um herauszufinden, was beim Android-Lebenszyklus passiert, ist es hilfreich zu wissen, wann die verschiedenen Lebenszyklusmethoden aufgerufen werden. So kannst du in DessertClicker nach möglichen Fehlern suchen.

Die einfache Möglichkeit hierfür ist die Verwendung der Android Logging API. Mithilfe von Logging können Sie kurze Nachrichten in eine Konsole schreiben, während die App ausgeführt wird. Außerdem können Sie sich dort ansehen, wann verschiedene Callbacks ausgelöst werden.

  1. Lade die DessertClicker App herunter und öffne sie in Android Studio.
  2. kompiliere und führe die App aus und tippe dann mehrmals auf das Bild des Desserts. Beachten Sie, dass sich der Wert für Desserts Sold (Desserts verkauft) und der Gesamtbetrag ändern.
  3. Öffnen Sie MainActivity.kt und untersuchen Sie die onCreate()-Methode für diese Aktivität
override fun onCreate(savedInstanceState: Bundle?) {
...
}

Vielleicht hast du im Diagramm zum Aktivitätslebenszyklus die onCreate()-Methode erkannt, weil du diesen Callback bereits verwendet hast. Es ist die Methode, die jede Aktivität implementieren muss. Bei der Methode onCreate() sollten Sie Ihre Initialisierungen einmalig für Ihre Aktivität ausführen. Beispielsweise können Sie in onCreate() das Layout aufladen, Klick-Listener definieren oder eine Datenbindung einrichten.

Die Lebenszyklusmethode onCreate() wird einmal aufgerufen, kurz nach der Initialisierung der Aktivität (also wenn das neue Activity-Objekt im Arbeitsspeicher erstellt wird). Nachdem onCreate() ausgeführt wurde, gilt die Aktivität als erstellt.

  1. Fügen Sie in der Methode onCreate() direkt nach dem Aufruf von super.onCreate() die folgende Zeile ein. Importieren Sie gegebenenfalls die Klasse Log. (Drücken Sie Alt+Enter oder Option+Enter auf einem Mac und wählen Sie Importieren aus.)
Log.i("MainActivity", "onCreate Called")

Die Klasse Log schreibt Nachrichten in den Logcat. Dieser Befehl besteht aus drei Teilen:

  • Der Schweregrad der Protokollnachricht, d. h. wie wichtig die Nachricht ist. In diesem Fall wird mit der Methode Log.i() eine Informationsnachricht geschrieben. Andere Methoden in der Log-Klasse sind Log.e() für Fehler oder Log.w() für Warnungen.
  • Das Tag im Log, in diesem Fall "MainActivity". Das Tag ist ein String, mit dem Sie Ihre Logeinträge leichter im Logcat finden. Das Tag ist normalerweise der Name der Klasse.
  • Die tatsächliche Lognachricht, ein kurzer String, der in diesem Fall "onCreate called" ist.
  1. Kompilieren und führen Sie die DessertClicker-App aus. Wenn Sie auf das Dessert tippen, sehen Sie keine Unterschiede der Funktionsweise in der App. Klicken Sie unten in Android Studio auf den Tab Logcat.



    Die Logcat ist die Konsole für die Protokollierung von Nachrichten. Hier werden Nachrichten von Android zu deiner App angezeigt, einschließlich der Nachrichten, die du mit der Log.i()-Methode oder anderen Log-Klassenmethoden explizit an das Protokoll sendest.
  2. Geben Sie im Bereich Logcat I/MainActivity in das Suchfeld ein.


    Der Logcat kann viele Nachrichten enthalten, von denen die meisten nicht relevant sind. Sie können die Logcat-Einträge auf viele Arten filtern, aber die Suche ist die einfachste. Weil Sie MainActivity als Log-Tag in Ihrem Code verwendet haben, können Sie dieses Tag zum Filtern des Logs verwenden. Wenn du I/ am Anfang hinzufügst, ist das eine informative Nachricht von Log.i().

    Deine Log-Nachricht enthält Datum und Uhrzeit, den Namen des Pakets (com.example.android.dessertclicker), dein Log-Tag (mit I/ am Anfang) und die eigentliche Nachricht. Da diese Nachricht im Protokoll angezeigt wird, wissen Sie, dass onCreate() ausgeführt wurde.

Schritt 2: onStart()-Methode implementieren

Die Lebenszyklusmethode onStart() wird direkt nach onCreate() aufgerufen. Nachdem onStart() ausgeführt wurde, sind Ihre Aktivitäten auf dem Bildschirm sichtbar. Im Gegensatz zu onCreate(), der nur einmal zum Initialisieren Ihrer Aktivität aufgerufen wird, kann onStart() im Lebenszyklus Ihrer Aktivität oft aufgerufen werden.

Beachten Sie, dass onStart() mit einer entsprechenden onStop()-Lebenszyklusmethode gekoppelt ist. Wenn der Nutzer Ihre App startet und dann zum Startbildschirm des Geräts zurückkehrt, wird die Aktivität angehalten und ist nicht mehr auf dem Bildschirm sichtbar.

  1. Wählen Sie in Android Studio, während MainActivity.kt geöffnet ist, Code > Überschreibungsmethoden aus oder drücken Sie Control+o. Es wird ein Dialogfeld mit einer umfangreichen Liste aller Methoden angezeigt, die in diesem Kurs überschrieben werden können.
  2. Gib onStart ein, um nach der richtigen Methode zu suchen. Mit dem Abwärtspfeil können Sie zum nächsten übereinstimmenden Element scrollen. Wählen Sie onStart() aus der Liste aus und klicken Sie auf OK, um den Boilerplate-Überschreibungscode einzufügen. Der Code sieht so aus:
override fun onStart() {
   super.onStart()
}
  1. Fügen Sie in der Methode onStart() eine Lognachricht hinzu:
override fun onStart() {
   super.onStart()

   Log.i("MainActivity", "onStart Called")
}
  1. Kompilieren und führen Sie die DessertClicker-App aus und öffnen Sie den Bereich Logcat. Geben Sie I/MainActivity in das Suchfeld ein, um das Protokoll zu filtern. Die Methoden onCreate() und onStart() wurden nacheinander aufgerufen und Ihre Aktivitäten sind auf dem Bildschirm sichtbar.
  2. Drücke auf dem Gerät die Startbildschirmtaste und kehre dann mit der zuletzt aufgerufenen Seite zur Aktivität zurück. Die Aktivität wird an der Stelle fortgesetzt, an der sie angehalten wurde. Sie enthält dieselben Werte. Außerdem wird onStart() ein zweites Mal in Logcat protokolliert. Die onCreate()-Methode wird in der Regel nicht noch einmal aufgerufen.

In dieser Aufgabe ändern Sie Ihre Anwendung so, dass eine beliebte Logging-Bibliothek mit dem Namen Timber verwendet wird. Timber bietet mehrere Vorteile gegenüber der integrierten Android-Klasse Log. Insbesondere die Bibliothek Timber:

  • Generiert das Log-Tag basierend auf dem Klassennamen.
  • Damit können Sie verhindern, dass Protokolle in einer Release-Version Ihrer Android-App angezeigt werden.
  • Ermöglicht die Integration mit Bibliotheken für Absturzberichte.

Den ersten Vorteil siehst du sofort, die anderen von dir schätzen, wenn du größere Apps erstellst und versendet.

Schritt 1: Timer zu Gradle hinzufügen

  1. Rufen Sie diesen Link zum Timber-Projekt auf GitHub auf und kopieren Sie die Codezeile unter der Überschrift Download, die mit dem Wort implementation beginnt. Die Codezeile sieht dann etwa so aus, wobei die Versionsnummer davon abweichen kann.
implementation 'com.jakewharton.timber:timber:4.7.1'
  1. Maximieren Sie in Android Studio im Bereich „Projekt: Android“ die Option Gradle-Skripts und öffnen Sie die Datei build.gradle (Modul: App).
  2. Fügen Sie im Abschnitt „Abhängigkeiten“ die kopierte Codezeile ein.
dependencies {
   ...
   implementation 'com.jakewharton.timber:timber:4.7.1'
}
  1. Klicken Sie rechts oben in Android Studio auf den Link Sync Now (Jetzt synchronisieren), um Gradle neu zu erstellen. Der Build sollte ohne Fehler ausgeführt werden.

Schritt 2: Anwendungsklasse erstellen und Timber initialisieren

In diesem Schritt erstellen Sie eine Application-Klasse. Application ist eine Basisklasse, die den globalen Anwendungsstatus für deine gesamte App enthält. Sie ist auch das Hauptobjekt, mit dem das Betriebssystem mit deiner App interagiert. Es gibt eine Application-Standardklasse, die Android verwendet, wenn du keine App angibst. Es gibt also immer ein Application-Objekt, das für deine App erstellt wird, ohne dass du etwas spezielles erstellen musst.

Timber verwendet die Klasse Application, da die gesamte Anwendung diese Logging-Bibliothek verwendet. Die Bibliothek muss einmal initialisiert werden, bevor alle anderen Funktionen eingerichtet sind. In solchen Fällen kannst du die Klasse Application blockieren und die Standardeinstellungen mit deiner eigenen benutzerdefinierten Implementierung überschreiben.

Nachdem du die Application-Klasse erstellt hast, musst du die Klasse im Android-Manifest angeben.

  1. Erstellen Sie im Paket dessertclicker eine neue Kotlin-Klasse mit dem Namen ClickerApplication. Maximieren Sie dazu app > java und klicken Sie mit der rechten Maustaste auf com.example.android.Desserclicker. Wähle Neu > Kotlin-Datei/Kurs aus.
  2. Geben Sie der Klasse den Namen ClickerApplication und legen Sie Kind auf Class fest. Klicken Sie auf OK.

In Android Studio wird eine neue ClickerApplication-Klasse erstellt und im Code-Editor geöffnet. Der Code sieht so aus:

package com.example.android.dessertclicker

class ClickerApplication {
}
  1. Ändere die Klassendefinition in eine Unterklasse von Application und importiere gegebenenfalls die Application-Klasse.
class ClickerApplication : Application() {
  1. Wenn Sie die onCreate()-Methode überschreiben möchten, wählen Sie Code > Überschreibungsmethoden aus oder drücken Sie Control+o.
class ClickerApplication : Application() {
   override fun onCreate() {
       super.onCreate()
   }
}
  1. Initialisieren Sie in dieser onCreate()-Methode die Timber-Bibliothek:
override fun onCreate() {
    super.onCreate()

    Timber.plant(Timber.DebugTree())
}

Mit dieser Codezeile wird die Bibliothek Timber für deine App initialisiert, damit du sie in deinen Aktivitäten verwenden kannst.

  1. Öffnen Sie die Datei AndroidManifest.xml.
  2. Fügen Sie oben im Element <application> ein neues Attribut für die Klasse ClickerApplication hinzu, damit Android weiß, dass anstelle der Standardklasse die Klasse Application verwendet wird.
<application
   android:name=".ClickerApplication"
...

Schritt 3: Timber-Protokollanweisungen hinzufügen

In diesem Schritt ändern Sie Ihre Log.i()-Aufrufe, sodass Timber verwendet wird. Anschließend implementieren Sie das Logging für alle anderen Lebenszyklusmethoden.

  1. Öffnen Sie MainActivity und scrollen Sie zu onCreate(). Ersetzen Sie Log.i() durch Timber.i() und entfernen Sie das Log-Tag.
Timber.i("onCreate called")

Wie bei der Log-Klasse verwendet Timber auch die i()-Methode für Informationsnachrichten. Beachten Sie, dass Sie mit Timber kein Log-Tag hinzufügen müssen. Timber verwendet automatisch den Namen der Klasse als Log-Tag.

  1. Oder ändere den Log-Aufruf in onStart():
override fun onStart() {
   super.onStart()

   Timber.i("onStart Called")
}
  1. Kompilieren und führen Sie die DessertClicker-App aus und öffnen Sie Logcat. Beachten Sie, dass Sie für onCreate() und onStart() weiterhin die gleichen Logeinträge sehen, nur aber Timber, die diese Nachrichten generieren, nicht die Klasse Log.
  2. Überschreibe die restlichen Lebenszyklusmethoden in deiner MainActivity und füge jeweils Timber Loganweisungen hinzu. Code:
override fun onResume() {
   super.onResume()
   Timber.i("onResume Called")
}

override fun onPause() {
   super.onPause()
   Timber.i("onPause Called")
}

override fun onStop() {
   super.onStop()
   Timber.i("onStop Called")
}

override fun onDestroy() {
   super.onDestroy()
   Timber.i("onDestroy Called")
}

override fun onRestart() {
   super.onRestart()
   Timber.i("onRestart Called")
}
  1. Kompilieren und führen Sie DessertClicker noch einmal durch und untersuchen Sie Logcat. Dieses Mal gibt es neben onCreate() und onStart() auch eine Protokollnachricht für den Lebenszyklus-Callback onResume().

Wenn eine Aktivität neu beginnt, werden alle drei Lebenszyklus-Callbacks in der angegebenen Reihenfolge angezeigt:

  • onCreate(), um die App zu erstellen
  • onStart(), um ihn zu starten und auf dem Bildschirm sichtbar zu machen.
  • onResume(), um den Aktivitätsschwerpunkt zu ändern und den Nutzer auf das Ereignis vorzubereiten.

Trotz des Namens wird die onResume()-Methode beim Start aufgerufen, auch wenn nichts fortgesetzt werden kann.

Nachdem die DessertClicker-App jetzt für die Protokollierung eingerichtet ist, können Sie die Anwendung auf verschiedene Arten verwenden und ermitteln, wie die Lebenszyklus-Callbacks als Reaktion auf diese Verwendungen ausgelöst werden.

Anwendungsfall 1: Öffnen und Schließen der Aktivität

Beginnen Sie mit dem grundlegendsten Anwendungsfall: Sie müssen Ihre App zum ersten Mal starten und dann vollständig schließen.

  1. Kompilieren und führen Sie die DessertClicker-App aus, falls sie noch nicht ausgeführt wird. Wie Sie sehen, werden die Callbacks onCreate(), onStart() und onResume() aufgerufen, wenn die Aktivität zum ersten Mal beginnt.
  2. Tippe mehrmals auf Cupcakes.
  3. Tippen Sie auf dem Gerät auf die Schaltfläche „Zurück“. Beachten Sie in Logcat, dass onPause(), onStop() und onDestroy() in dieser Reihenfolge aufgerufen werden.

    In diesem Fall wird die Aktivität (und die App) über die Schaltfläche „Zurück“ vollständig geschlossen. Durch die Ausführung der Methode onDestroy() wurde die Aktivität vollständig beendet und kann automatisch bereinigt werden. Garagentorsammlung bezieht sich auf die automatische Bereinigung von Objekten, die Sie nicht mehr verwenden. Nach dem Aufruf von onDestroy() weiß das Betriebssystem, dass diese Ressourcen verworfen werden können, und bereinigt den Arbeitsspeicher.

    Deine Aktivitäten werden eventuell auch vollständig beendet, wenn dein Code die App manuell mit der Aktivität finish() aufruft oder der Nutzer das Beenden der App erzwingt. So kann er beispielsweise durch Tippen auf das X in der Ecke des Fensters die Beenden der App erzwingen. Das Android-System fährt möglicherweise auch Ihre Aktivitäten selbst herunter, wenn Ihre App längere Zeit nicht auf dem Bildschirm angezeigt wurde. Das trägt dazu bei, dass der Akku geschont wird und die Ressourcen deiner App von anderen Apps genutzt werden können.
  4. Mit dem Bildschirm „Zuletzt verwendet“ kehren Sie zur App zurück. Hier ist die Logcat:


    Die Aktivität wurde im vorherigen Schritt gelöscht. Wenn Sie zur App zurückkehren, startet Android eine neue Aktivität und ruft die Methode onCreate(), onStart() und onResume() auf. Beachten Sie, dass keine der DessertClicker-Statistiken aus der vorherigen Aktivität beibehalten wurde.

    Das Wichtigste ist hier, dass onCreate() und onDestroy() während der Lifetime einer einzelnen Aktivitätsinstanz nur einmal aufgerufen werden: onCreate(), um die App zum ersten Mal zu initialisieren, und onDestroy(), um die von Ihrer App verwendeten Ressourcen zu bereinigen.

    Die onCreate()-Methode ist ein wichtiger Schritt. Hier findet die erstmalige Initialisierung statt, bei der Sie das Layout zum ersten Mal durch Inflieren der Variablen einrichten und wo Sie Ihre Variablen initialisieren.

Anwendungsfall 2: Aktivität verlassen und zurück

Nachdem Sie die App gestartet und vollständig geschlossen haben, haben Sie den Großteil der Lebenszyklusstatus gesehen, wenn die Aktivität zum ersten Mal erstellt wird. Außerdem sehen Sie alle Lebenszyklusphasen, die passieren, wenn die Aktivität vollständig beendet und zerstört wird. Wenn Nutzer jedoch mit ihren Android-Geräten interagieren, wechseln sie zwischen Apps, kehren zur Startseite zurück, starten neue Apps und bewältigen Unterbrechungen durch andere Aktivitäten wie Anrufe.

Ihre Aktivität wird nicht jedes Mal geschlossen, wenn der Nutzer die Aktivität verlässt:

  • Wenn deine Aktivitäten nicht mehr auf dem Bildschirm zu sehen sind, wird sie als Hintergrund bezeichnet. Dagegen ist die Aktivität im Vordergrund oder auf dem Bildschirm.
  • Wenn der Nutzer zu Ihrer App zurückkehrt, wird diese Aktivität neu gestartet und ist wieder sichtbar. Dieser Teil des Lebenszyklus wird als sichtbarer Lebenszyklus der App bezeichnet.

Wenn Ihre App im Hintergrund ausgeführt wird, sollte sie nicht aktiv ausgeführt werden, um Systemressourcen und die Akkulaufzeit zu verlängern. Du verwendest den Activity-Lebenszyklus und die zugehörigen Callbacks, um zu erfahren, wann sich deine App in den Hintergrund verschiebt. So kannst du laufende Vorgänge pausieren. Starte den Vorgang dann neu, wenn deine App im Vordergrund ausgeführt wird.

Stellen Sie sich eine App vor, die eine Physiksimulation simuliert. Für die Entscheidung, wo sich alle Objekte in der Simulation befinden, und Anzeige. Wenn die Simulation durch einen Telefonanruf unterbrochen wird, ist der Nutzer möglicherweise verwirrt oder sogar verärgert, sodass er die App zurückspult und sieht, dass die Simulation abgeschlossen ist.

Es gibt auch einen Leistungsgrund dafür. Angenommen, der Nutzer hat 20 Apps geöffnet, in denen CPU-intensive physikalische Simulationen verwendet werden. Wenn diese Apps nicht auf dem Bildschirm zu sehen sind, aber dennoch starke Rendering-Berechnungen im Hintergrund erfolgen, wirkt sich dies negativ auf die Leistung des gesamten Smartphones aus.

In diesem Schritt sehen Sie sich den Aktivitätslebenszyklus an, wenn die App in den Hintergrund verschoben und wieder in den Vordergrund zurückkehrt.

  1. Klicke während der Ausführung der DessertClicker-App einige Male auf den Cupcake.
  2. Drücken Sie auf Ihrem Gerät die Startbildschirmtaste und beobachten Sie die Logcat in Android Studio. Wenn Sie zum Startbildschirm zurückkehren, wird die App im Hintergrund ausgeführt und nicht vollständig geschlossen. Die Methode onPause() und onStop() werden aufgerufen, onDestroy() aber nicht.


    Wenn onPause() aufgerufen wird, hat die App keinen Fokus mehr. Nach dem onStop() ist die App nicht mehr auf dem Bildschirm sichtbar. Obwohl die Aktivität gestoppt wurde, befindet sich das Activity-Objekt noch im Arbeitsspeicher, im Hintergrund. Die Aktivität wurde nicht gelöscht. Der Nutzer kehrt möglicherweise zur App zurück, sodass Android Ihre Aktivitätsressourcen beibehält.
  3. Verwende den Bildschirm „Zuletzt verwendet“, um zur App zurückzukehren. Beachte, dass die Aktivität in Logcat mit onRestart() und onStart() neu gestartet und dann mit onResume() fortgesetzt wird.


    Wenn die Aktivität wieder in den Vordergrund rückt, wird die onCreate()-Methode nicht noch einmal aufgerufen. Das Aktivitätsobjekt wurde nicht gelöscht, sodass es nicht noch einmal erstellt werden muss. Statt onCreate() wird die Methode onRestart() aufgerufen. Wenn die Aktivität wieder in den Vordergrund rückt, wird die Zahl Verkaufte Träger beibehalten.
  4. Starte mindestens eine andere App als „DessertClicker“, damit auf dem Display des Geräts einige Apps angezeigt werden.
  5. Rufe den Bildschirm „Zuletzt verwendet“ auf und öffne eine weitere Aktivität. Rufe dann die zuletzt verwendeten Apps auf und setze DessertClicker wieder in den Vordergrund.

    Hier siehst du dieselben Callbacks in Logcat wie auf der Startbildschirmtaste. onPause() und onStop() werden aufgerufen, wenn die App in den Hintergrund wechselt, und dann onRestart(), onStart() und onResume(), wenn sie ausgeführt wird.

    Der wichtige Punkt ist, dass onStart() und onStop() mehrmals aufgerufen werden, wenn der Nutzer die Aktivität aufruft und von ihr ausgeht. Sie sollten diese Methoden überschreiben, um die App zu stoppen, wenn sie in den Hintergrund verschoben wird, oder sie neu zu starten, wenn sie wieder in den Vordergrund rückt.

    Was ist mit onRestart()? Die onRestart()-Methode ist ähnlich wie onCreate(). Entweder onCreate() oder onRestart() wird aufgerufen, bevor die Aktivität sichtbar wird. Die Methode onCreate() wird nur beim ersten Mal und onRestart() danach aufgerufen. Mit der onRestart()-Methode können Sie Code generieren, den Sie nur dann aufrufen möchten, wenn Ihre Aktivität nicht zum ersten Mal gestartet wird.

Anwendungsfall 3: Aktivität teilweise ausblenden

Du hast gelernt, dass, wenn eine App gestartet wird und onStart() aufgerufen wird, die App auf dem Bildschirm sichtbar ist. Wenn die App fortgesetzt und onResume() aufgerufen wird, erhält die App den Nutzerfokus. Der Teil des Lebenszyklus, in dem die App vollständig auf dem Bildschirm erscheint und den Nutzerfokus hat, wird als interaktiver Lebenszyklus bezeichnet.

Wenn die App in den Hintergrund rückt, geht der Fokus nach onPause() verloren und die App wird nach onStop() nicht mehr sichtbar sein.

Der Unterschied zwischen Fokus und Sichtbarkeit ist wichtig, da eine Aktivität zwar teilweise auf dem Bildschirm sichtbar sein kann, nicht aber den Nutzerfokus. In diesem Schritt betrachten Sie einen Fall, bei dem eine Aktivität nur teilweise sichtbar ist, aber keinen Nutzerfokus hat.

  1. Wenn die DessertClicker-App ausgeführt wird, klicken Sie rechts oben auf die Schaltfläche Teilen.




    Die Freigabeaktivitäten werden in der unteren Hälfte des Bildschirms angezeigt, die Aktivitäten sind aber weiterhin in der oberen Hälfte sichtbar.
  2. Prüfen Sie Logcat und stellen Sie fest, dass nur onPause() aufgerufen wurde.


    In diesem Anwendungsfall wird onStop() nicht aufgerufen, weil die Aktivität noch teilweise sichtbar ist. Aber diese Aktivität hat keinen Nutzerfokus und der Nutzer kann nicht mit ihm interagieren. Bei der Aktivität „Teilen“ im Vordergrund steht der Nutzer im Fokus.

    Warum ist dieser Unterschied wichtig? Denken Sie an die Physik-App. Möglicherweise möchten Sie die Simulation beenden, wenn die App im Hintergrund ausgeführt wird, und sie weiter ausführen, wenn sie teilweise verdeckt ist. In diesem Fall würdest du die Simulation in onStop() beenden. Wenn du möchtest, dass die Simulation beendet wird, wenn die Aktivität teilweise verdeckt wird, füge den Code ein, um die Simulation in onPause() zu beenden.

    Der Code, der in onPause() ausgeführt wird, blockiert andere Elemente. Achte also darauf, dass der Code in onPause() schlank ist. Wenn beispielsweise ein Telefonanruf eingeht, kann der Code in onPause() die Benachrichtigung für eingehende Anrufe verzögern.
  3. Wenn du außerhalb des Freigabedialogs klickst, kehrst du zur App zurück und siehst, dass onResume() aufgerufen wird.

    Sowohl onResume() als auch onPause() müssen sich im Fokus befinden. Die Methode onResume() wird aufgerufen, wenn die Aktivität fokussiert ist, und onPause(), wenn die Aktivität verloren geht.

Der Lebenszyklus von Android-Fragmenten ähnelt dem Aktivitätslebenszyklus und umfasst außerdem mehrere fragmentspezifische Methoden.

In dieser Aufgabe sehen Sie sich die AndroidTrivia-App an, die Sie in früheren Codelabs erstellt haben. Außerdem fügen Sie Logging hinzu, um den Fragmentlebenszyklus zu untersuchen. Mit der AndroidTrivia App können Sie Fragen zur Android-Entwicklung beantworten. Wenn Sie drei Fragen in Folge richtig beantworten, gewinnen Sie das Spiel.

Jeder Bildschirm in der Android Trivia App ist ein Fragment.

Der Einfachheit halber verwenden Sie für diese Aufgabe die Android Logging API und nicht die Timber-Bibliothek.

  1. Öffnen Sie die AndroidTrivia-App aus dem letzten Codelab oder laden Sie den AndroidTrivia-Lösungscode von GitHub herunter.
  2. Öffnen Sie die Datei TitleFragment.kt. Hinweis: Android Studio zeigt möglicherweise Bindungsfehler und ungelöste Referenzfehler an, bis du die App neu erstellst.
  3. Scrollen Sie nach unten zur Methode onCreateView(). Hier sehen Sie, dass das Layout des Fragments zu hoch ist und eine Datenbindung erfolgt.
  4. Fügen Sie der Methode onCreateView() eine Logging-Anweisung hinzu, zwischen der Zeile und setHasOptionsMenu() und dem letzten Aufruf, der zurückgegeben werden soll:
setHasOptionsMenu(true)

Log.i("TitleFragment", "onCreateView called")

return binding.root
  1. Fügen Sie direkt unter der Methode onCreateView() Logging-Anweisungen für jede der verbleibenden Fragmentmethoden hinzu. Hier ist der Code:
override fun onAttach(context: Context?) {
   super.onAttach(context)
   Log.i("TitleFragment", "onAttach called")
}
override fun onCreate(savedInstanceState: Bundle?) {
   super.onCreate(savedInstanceState)
   Log.i("TitleFragment", "onCreate called")
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
   super.onActivityCreated(savedInstanceState)
   Log.i("TitleFragment", "onActivityCreated called")
}
override fun onStart() {
   super.onStart()
   Log.i("TitleFragment", "onStart called")
}
override fun onResume() {
   super.onResume()
   Log.i("TitleFragment", "onResume called")
}
override fun onPause() {
   super.onPause()
   Log.i("TitleFragment", "onPause called")
}
override fun onStop() {
   super.onStop()
   Log.i("TitleFragment", "onStop called")
}
override fun onDestroyView() {
   super.onDestroyView()
   Log.i("TitleFragment", "onDestroyView called")
}
override fun onDetach() {
   super.onDetach()
   Log.i("TitleFragment", "onDetach called")
}
  1. Kompilieren und führen Sie die App aus und öffnen Sie Logcat.
  2. Geben Sie I/TitleFragment in das Suchfeld ein, um das Protokoll zu filtern. Nach dem Start der App sieht die Logcat so aus:

Hier siehst du den gesamten Startlebenszyklus des Fragments, einschließlich dieser Callbacks:

  • onAttach(): Wird aufgerufen, wenn das Fragment der Inhaberaktivität zugeordnet ist.
  • onCreate(): Ähnlich wie onCreate() für die Aktivität wird onCreate() für das Fragment aufgerufen, um die erste Fragmenterstellung durchzuführen (außer dem Layout).
  • onCreateView(): Wird aufgerufen, um das Layout des Fragments zu erhöhen.
  • onActivityCreated(): Wird aufgerufen, wenn die Inhaberaktivität onCreate() abgeschlossen ist. Dein Fragment kann erst auf die Aktivität zugreifen, wenn diese Methode aufgerufen wird.
  • onStart(): Wird aufgerufen, wenn das Fragment sichtbar wird; parallel zu den Aktivitäten onStart().
  • onResume(): Wird aufgerufen, wenn das Fragment den Nutzerfokus erhält; parallel zu den onResume()-Aktivitäten.
  1. Tippe auf die Schaltfläche Spielen, um zum Quiz zu gelangen, und merke dir jetzt die Logcat.

Beim Öffnen des nächsten Fragments wird das Titelfragment geschlossen und die folgenden Lebenszyklusmethoden werden aufgerufen:

  • onPause(): Wird aufgerufen, wenn das Fragment den Nutzerfokus verliert, parallel zu den onPause()-Aktivitäten.
  • onStop(): Wird aufgerufen, wenn das Fragment nicht mehr auf dem Bildschirm sichtbar ist; parallel zu den onStop()-Aktivitäten.
  • onDestroyView(): Wird aufgerufen, wenn die Ansicht des Fragments nicht mehr benötigt wird, um die mit dieser Ansicht verknüpften Ressourcen zu bereinigen.
  1. Tippe in der App auf den Aufwärtspfeil (den Pfeil links oben auf dem Bildschirm), um zum Titelfragment zurückzukehren.


    diesmal werden onAttach() und onCreate() nicht aufgerufen. Das Fragment-Objekt ist noch vorhanden und ist noch an seine Inhaberaktivität angehängt. Der Lebenszyklus beginnt also wieder mit onCreateView().
  2. Drücken Sie die Startbildschirmtaste des Geräts. Im Logcat wird angegeben, dass nur onPause() und onStop() aufgerufen werden. Dabei ist das gleiche Verhalten wie bei der Aktivität: Wenn Sie nach Hause zurückkehren, werden die Aktivität und das Fragment in den Hintergrund verschoben.
  3. Nutze den Bildschirm „Zuletzt verwendet“, um zur App zurückzukehren. Genau wie bei der Aktivität werden die Methoden onStart() und onResume() aufgerufen, um das Fragment im Vordergrund anzuzeigen.

Android Studio-Projekt: DessertClickerLogs

Lebenszyklus der Aktivität

  • Der Aktivitätslebenszyklus besteht aus mehreren Status, über die eine Aktivität migriert wird. Der Aktivitätslebenszyklus beginnt mit dem ersten Erstellen der Aktivität und endet mit dem Löschen der Aktivität.
  • Wenn der Nutzer zwischen Aktivitäten und innerhalb und außerhalb Ihrer App wechselt, wechselt jede Aktivität zwischen den Status im Lebenszyklus der Aktivität.
  • Für jeden Status im Aktivitätslebenszyklus gibt es eine entsprechende Callback-Methode, die Sie in Ihrer Activity-Klasse überschreiben können. Es gibt sieben Lebenszyklusmethoden:
    onCreate()
    onStart()
    onPause()
    onRestart()
    onResume()
    onStop()
    onDestroy()
  • zum Hinzufügen von Verhalten, das zu einem Übergang zu einer Lebenszyklusphase führt, überschreiben Sie die Callback-Methode des Status.
  • Wenn Sie den Klassen in Android Studio Methoden zum Überschreiben von Skeleton hinzufügen möchten, wählen Sie Code > Überschreibungsmethoden aus oder drücken Sie Control+o.

Protokollierung mit Log

  • Mit der Android Logging API, insbesondere der Klasse Log, kannst du kurze Nachrichten schreiben, die in Android in der Logcat angezeigt werden.
  • Mit Log.i() eine Informationsnachricht schreiben. Diese Methode verwendet zwei Argumente: das Tag des Log-Tags (in der Regel der Name der Klasse) und das Log-Tag message (ein kurzer String).
  • Verwenden Sie in Android Studio den Bereich Logcat, um die Systemprotokolle einschließlich der Meldungen zu sehen, die Sie schreiben.

Protokollierung mit Timber

Timber ist eine Logging-Bibliothek mit mehreren Vorteilen gegenüber der Android Logging API. Insbesondere die Bibliothek Timber:

  • Generiert das Log-Tag basierend auf dem Klassennamen.
  • Kann helfen, Protokolle in einer Release-Version Ihrer Android-App anzuzeigen.
  • Ermöglicht die Integration mit Bibliotheken für Absturzberichte.

Wenn du Timber verwenden möchtest, musst du die Abhängigkeit deiner Gradle-Datei hinzufügen und die Klasse Application zur Initialisierung der Erweiterung erweitern:

  • Application ist eine Basisklasse, die den globalen Anwendungsstatus für deine gesamte App enthält. Es gibt eine Application-Standardklasse, die von Android verwendet wird, wenn du keine Klasse angibst. Sie können Ihre eigene Unterklasse Application erstellen, um App-weite Bibliotheken wie Timber zu initialisieren.
  • Füge deiner App deine benutzerdefinierte Application-Klasse hinzu, indem du im Android-Manifest dem <application>-Element das Attribut android:name hinzufügst. Vergiss das nicht!
  • Mit Timber.i() Logeinträge mit Timber schreiben. Diese Methode verwendet nur ein Argument: die zu schreibende Nachricht. Das Log-Tag (der Name der Klasse) wird automatisch hinzugefügt.

Udacity-Kurs:

Android-Entwicklerdokumentation:

Sonstiges:

In diesem Abschnitt werden mögliche Hausaufgaben für Schüler oder Studenten aufgeführt, die an diesem von einem Kursleiter geleiteten Codelab arbeiten. Die Lehrkraft kann Folgendes tun:

  • Bei Bedarf können Sie die entsprechenden Aufgaben zuweisen.
  • Schülern mitteilen, wie sie Aufgaben für die Aufgabe abgeben
  • Benoten Sie die Hausaufgaben.

Lehrkräfte können diese Vorschläge so oft oder so oft verwenden, wie sie möchten. anderen Aufgaben können sie nach Belieben zugewiesen werden.

Wenn Sie alleine an diesem Codelab arbeiten, können Sie Ihr Wissen mit diesen Hausaufgaben testen.

Eine App ändern

Öffnen Sie die DiceRoller App aus Lektion 1. Hier können Sie die DiceRoller-App herunterladen. Fügen Sie dieser App Timber-Unterstützung hinzu. Gehen Sie dabei genauso vor wie bei der DessertClicker-App. Überschreiben Sie alle Lebenszyklus-Callbacks und fügen Sie für jeden Callback Logging-Nachrichten hinzu.

Diese Fragen beantworten

Frage 1

Welche der folgenden Optionen ist KEIN Status für einen Aktivitätslebenszyklus?

  • Gestartet
  • Warten
  • Erstellt
  • Gelöscht

Frage 2

Mit welcher Lebenszyklusmethode wird eine Aktivität sichtbar?

  • onPause()
  • onVisible()
  • onStart()
  • onDestroy()

Frage 3

Welche Lebenszyklusmethode wird aufgerufen, um einen Aktivitätsschwerpunkt zu erreichen?

  • onResume()
  • onVisible()
  • onStart()
  • onFocus()

Frage 4

Wann wird onCreate() in einer Aktivität aufgerufen?

  • Jedes Mal, wenn die Aktivität für den Nutzer sichtbar ist.
  • Jedes Mal, wenn die Aktivität im Hintergrund auftritt.
  • Nur einmal, wenn die Aktivität erstellt wird.
  • Nur einmal, wenn die Aktivität fortgesetzt wird.

App zur Benotung einreichen

Prüfen Sie, ob die App die folgenden Anforderungen erfüllt:

  • Eine Abhängigkeit von Timber in der build.gradle-Datei für die App.
  • Eine benutzerdefinierte Unterklasse von Application, die Timber in onCreate() initialisiert.
  • Ein Attribut für diese benutzerdefinierte Unterklasse im Android-Manifest.
  • Die Methode wird in MainActivity für alle Lebenszyklus-Callback-Methoden überschrieben, mit Logging-Aufrufen für Timber.i().

Mit der nächsten Lektion beginnen: 4.2: Komplexe Lebenszyklussituationen

Links zu anderen Codelabs in diesem Kurs finden Sie auf der Landingpage zu Kotlin-Grundlagen für Android.