Android Kotlin Fundamentals 04.1: cykle życia i logowanie

Te ćwiczenia są częścią kursu Android Kotlin Fundamentals. Skorzystaj z tego kursu, jeśli będziesz wykonywać kolejno kilka ćwiczeń z programowania. Wszystkie ćwiczenia z kursu są wymienione na stronie docelowej ćwiczeń z programowania na temat Kotlin.

Wstęp

Z tego modułu ćwiczeń dowiesz się więcej o podstawowym elemencie Androida: aktywności i cyklu życia fragmentu. Cykl życia aktywności to zestaw stanów, w jakich może pozostawać aktywność. Cykl życia rozciąga się od momentu utworzenia aktywności do momentu zniszczenia jej. System odzyskuje te zasoby. Gdy użytkownik przechodzi między aktywnościami w aplikacji (oraz w aplikacji, i poza nią), każda z nich przechodzi z jednego stanu na inny.

Cykl życia fragmentu jest bardzo podobny do cyklu aktywności. Te ćwiczenia skupiają się przede wszystkim na ćwiczeniach, z krótkim omówieniem fragmentów na końcu.

Jako deweloper aplikacji na Androida musisz znać cykl życia aktywności. Jeśli aktywność nie reaguje na zmiany stanu cyklu życia, aplikacja może generować dziwne błędy, wprowadzać użytkowników w błąd lub wykorzystywać zbyt wiele zasobów systemu Android. Znajomość cyklu życia urządzenia z Androidem i odpowiednie reagowanie na zmiany w tym cyklu mają kluczowe znaczenie dla dobrych użytkowników Androida.

Co warto wiedzieć

  • Czym jest aktywność i jak ją utworzyć w aplikacji
  • Działanie metody onCreate() i rodzaje wykonywanych operacji w tej metodzie.
  • Jak tworzyć układy XML dla aktywności i jak aktualizować układ w czasie działania.

Czego się nauczysz:

  • Informacje o drukowaniu danych dziennika w narzędziu Logcat (nazywanym czasem konsolą Android lub monitorem Androida).
  • Podstawowe informacje o cyklach życia Activity i Fragment oraz wywołania zwrotne, które są wywoływane, gdy aktywność przechodzi między stanami.
  • Jak zastąpić metody wywołania zwrotnego cyklu życia, aby wykonywać operacje w różnych momentach cyklu życia aktywności.
  • Jak korzystać z biblioteki Timber do logowania się w aplikacji.

Co chcesz

  • Zmodyfikuj aplikację startową o nazwie DessertClicker, aby dodać informacje logowania wyświetlane w Logcat.
  • Zastąp metody wywołania zwrotnego cyklu życia i zapisz zmiany w stanie aktywności.
  • Uruchom aplikację i zanotuj informacje logowania wyświetlane podczas uruchamiania, zatrzymywania i wznawiania tej aktywności.
  • Zmodyfikuj aplikację tak, aby używała biblioteki Timber.
  • Dodaj logowanie do aplikacji AndroidTrivia i monitoruj zmiany stanu fragmentów.

W tym ćwiczeniu z programowania korzystasz z aplikacji startowej o nazwie DessertClicker. Za każdym razem, gdy użytkownik kliknie deser na ekranie, dochodzi do wyboru deseru. Aplikacja aktualizuje wartości w układie według liczby kupionych deserów i łącznej kwoty wydanej przez użytkownika.

Ta aplikacja zawiera kilka błędów związanych z cyklem życia Androida: na przykład w pewnych okolicznościach aplikacja resetuje wartości deseru na wartość 0, a aplikacja kontynuuje używanie zasobów systemowych nawet wtedy, gdy jest uruchomiona w tle. Poznanie cyklu życia Androida pomoże Ci zrozumieć, dlaczego te problemy występują i jak je rozwiązać.

Każda aktywność i każdy fragment mają tzw. cykl życia. Wiąże się to z cyklem życia zwierząt, w tym z cyklu motyla – różne stany motyla ukazują jego wzrost od narodzin po w pełni ukształtowane dorosłość do śmierci.

Analogicznie cykl życia aktywności składa się z różnych stanów, w których dane działanie może przejść, od momentu inicjowania aktywności do jej zniszczenia i odzyskania jej pamięci przez system. Gdy użytkownik uruchamia aplikację, przechodzi między aktywnościami, przechodzi między aplikacją i poza nią, a aplikacja opuści stan, aktywność ulegnie zmianie. Poniższy schemat przedstawia wszystkie stany cyklu życia aktywności. Stany te wskazują stan danej aktywności.

Często warto zmienić pewne działanie lub uruchomić kod po zmianie stanu cyklu życia aktywności. Dlatego sama klasa Activity i wszystkie jej klasy podrzędne, takie jak Activity, takie jak AppCompatActivity, wprowadzają zestaw metod wywołań zwrotnych cyklu życia. Android wywołuje te wywołania zwrotne, gdy aktywność przechodzi z jednego stanu do innego. Możesz zastąpić te metody w swoich działaniach, by wykonać zadania w odpowiedzi na zmianę stanu cyklu życia. Ten diagram przedstawia stany cyklu życia wraz z dostępnymi zastępnymi wywołaniami zwrotnymi.

Fragment ma też cykl życia. Cykl życia fragmentu jest podobny do cyklu życia aktywności, więc wiele informacji ma zastosowanie w obu przypadkach. W tym ćwiczeniu skupiasz się na cyklu życia aktywności, ponieważ jest to podstawowa część Androida i najłatwiejsza do obserwowania w prostej aplikacji. Oto odpowiedni schemat dla cyklu życia fragmentu:

Ważne jest, by wiedzieć, kiedy te wywołania zwrotne są wywoływane i co robić w przypadku poszczególnych metod. Oba te diagramy są jednak skomplikowane. Podczas tych ćwiczeń z programowania zamiast czytać informacje o poszczególnych stanach i odwołaniach, przeprowadzisz badania i zrozumiesz, co się dzieje.

Krok 1. Sprawdź metodę onCreate() i dodaj logowanie

Aby dowiedzieć się, co dzieje się z cyklem życia Androida, warto wiedzieć, kiedy są wywoływane różne metody cyklu życia. Dzięki temu możesz znaleźć miejsca na problemy, korzystając z DessertClicker.

Najprostszym sposobem jest użycie interfejsu Android Logging API. Logowanie umożliwia zapisywanie krótkich wiadomości w konsoli podczas działania aplikacji. Możesz ich też używać, aby wyświetlać powiadomienia o wywołaniu różnych wywołań zwrotnych.

  1. Pobierz aplikację DessertClicker starter i otwórz ją w Android Studio.
  2. Skompiluj i uruchom aplikację, a następnie kliknij kilka razy zdjęcie deseru. Zwróć uwagę, jak zmienia się wartość opcji Sprzedane desery i łączna kwota w dolarach.
  3. Otwórz MainActivity.kt i sprawdź metodę onCreate() dla tego działania
override fun onCreate(savedInstanceState: Bundle?) {
...
}

Na schemacie cyklu życia być może znasz metodę onCreate(), bo zdarzyło Ci się już używać tego wywołania zwrotnego. To jedyna metoda, jaką musi stosować każde działanie. Metoda onCreate() wskazuje jednorazowe inicjowanie aktywności. Na przykład w onCreate() możesz zastępować układ, zdefiniować odbiorniki kliknięć lub skonfigurować wiązanie danych.

Metoda cyklu życia onCreate() jest wywoływana raz po zainicjowaniu aktywności (po utworzeniu nowego obiektu Activity w pamięci). Po wykonaniu działania onCreate() uznawane jest za utworzone.

  1. W metodzie onCreate() tuż po wywołaniu funkcji super.onCreate() dodaj ten wiersz. W razie potrzeby zaimportuj klasę Log. (Naciśnij Alt+Enter lub Option+Enter na Macu i wybierz Importuj).
Log.i("MainActivity", "onCreate Called")

Klasa Log zapisuje wiadomości w narzędziu Logcat. To polecenie składa się z 3 części:

  • Waga komunikatu logu, czyli jego znaczenie. W takim przypadku metoda Log.i() zapisuje informacje. Inne metody klasy Log to Log.e() w przypadku błędów i Log.w() w przypadku ostrzeżeń.
  • Tag logu, w tym przypadku "MainActivity". Tag to ciąg znaków, który ułatwia znajdowanie komunikatów logu w LogCat. Tag to zwykle nazwa klasy.
  • Rzeczywisty komunikat z dziennika, czyli krótki ciąg znaków, w tym przypadku "onCreate called".
  1. Skompiluj i uruchom aplikację DessertClicker. Po kliknięciu deseru nie zauważysz żadnych różnic w działaniu. W Android Studio u dołu ekranu kliknij kartę Logcat.



    Logcat to konsola do logowania wiadomości. Tutaj pojawiają się wiadomości na temat aplikacji z Androida, w tym wiadomości wysłane do dziennika przy użyciu metody Log.i() lub innych metod klasy Log.
  2. W polu wyszukiwania w panelu Logcat wpisz I/MainActivity.


    Logcat może zawierać wiele wiadomości, z których większość jest nieprzydatna. Wpisy w narzędziu Logcat możesz filtrować na wiele sposobów, ale wyszukiwanie jest najłatwiejsze. Ponieważ w kodzie został użyty MainActivity, możesz użyć tego tagu do filtrowania dziennika. Dodanie I/ na początku oznacza, że został utworzony przez Log.i().

    Wiadomość zawiera datę i godzinę, nazwę pakietu (com.example.android.dessertclicker), tag logu (z I/ na początku) i rzeczywisty komunikat. Ten komunikat pojawia się w dzienniku, więc wiesz, że polecenie onCreate() zostało wykonane.

Krok 2. Zaimplementuj metodę onStart()

Metoda cyklu życia onStart() jest wywoływana tuż po elemencie onCreate(). Po uruchomieniu usługi onStart() Twoja aktywność jest widoczna na ekranie. W przeciwieństwie do onCreate(), który jest wywoływany tylko raz, inicjując aktywność, onStart() może zostać wywołany wielokrotnie w cyklu życia.

Zwróć uwagę, że element onStart() jest sparowany z odpowiednią metodą cyklu życia onStop(). Jeśli użytkownik uruchomi aplikację, a potem wróci do ekranu głównego urządzenia, aktywność zostanie zatrzymana i nie będzie już widoczna na ekranie.

  1. W Androidzie Studio z otwartą aplikacją MainActivity.kt wybierz Kod > Zastąp metody lub naciśnij Control+o. Pojawi się okno z listą wszystkich metod, które możesz zastąpić w tych zajęciach.
  2. Zacznij wpisywać onStart, aby wyszukać właściwą metodę. Aby przewinąć do następnego pasującego elementu, użyj strzałki w dół. Wybierz onStart() z listy i kliknij OK, aby wstawić powtarzalny kod zastąpienia. Wygląda on tak:
override fun onStart() {
   super.onStart()
}
  1. W metodzie onStart() dodaj komunikat logu:
override fun onStart() {
   super.onStart()

   Log.i("MainActivity", "onStart Called")
}
  1. Skompiluj i uruchom aplikację DessertClicker, a następnie otwórz panel Logcat. Aby przefiltrować dziennik, wpisz I/MainActivity w polu wyszukiwania. Zwróć uwagę, że obie te metody: onCreate() i onStart() – zostały wywołane po drugiej, a Twoja aktywność jest widoczna na ekranie.
  2. Naciśnij przycisk ekranu głównego na urządzeniu, a następnie użyj ekranu Ostatnie, aby wrócić do aktywności. Zauważ, że aktywność wznawia się w miejscu, w którym została przerwana, z tymi samymi wartościami, a także, że onStart() jest logowana po raz drugi do Logcat. Zwróć też uwagę, że metoda onCreate() zwykle nie jest wywoływana ponownie.

W tym zadaniu modyfikujesz aplikację, aby korzystała z popularnej biblioteki logowania o nazwie Timber. Timber ma kilka zalet w porównaniu z wbudowaną klasą Androida Log. Biblioteka Timber:

  • Generuje tag dziennika na podstawie nazwy klasy.
  • Pomaga uniknąć wyświetlania dzienników w nowej wersji aplikacji na Androida.
  • Pozwala na integrację z bibliotekami raportowania awarii.

Od razu zobaczysz pierwszą korzyść. Pozostałe są dla Ciebie cenne podczas tworzenia i wysyłania większych aplikacji.

Krok 1. Dodaj drewno do Gradle

  1. Kliknij ten link i przejdź do projektu Timber na GitHubie. Skopiuj wiersz kodu z nagłówkiem Pobierz, który zaczyna się od słowa implementation. Wiersz kodu wygląda mniej więcej tak, ale numer wersji może być inny.
implementation 'com.jakewharton.timber:timber:4.7.1'
  1. W Android Studio w projekcie Android: rozwiń Gradle Scripts i otwórz plik build.gradle (Module: app).
  2. W sekcji zależności wklej skopiowany wiersz kodu.
dependencies {
   ...
   implementation 'com.jakewharton.timber:timber:4.7.1'
}
  1. Aby ponownie utworzyć Gradle, kliknij link Sync Now (Synchronizuj teraz) w prawym górnym rogu w Android Studio. Kompilacja powinna się zakończyć bez błędów.

Krok 2. Utwórz klasę aplikacji i zainicjuj Timber

W tym kroku utworzysz klasę Application. Application to klasa podstawowa, która zawiera stan aplikacji globalnej dla całej aplikacji. Jest to główny obiekt, którego system operacyjny używa do interakcji z Twoją aplikacją. Jeśli nie podasz klasy, której używa Android, domyślna będzie klasa Application, więc zawsze jest to obiekt Application utworzony dla Twojej aplikacji. Nie musisz nic robić, aby ją utworzyć.

Timber używa klasy Application, ponieważ cała aplikacja będzie używać tej biblioteki logowania, a w przypadku pozostałej biblioteki musi zostać zainicjowana tylko raz. W takich przypadkach możesz podklasować klasę Application i zastępować wartości domyślne własną implementacją.

Po utworzeniu klasy Application musisz określić ją w pliku manifestu Androida.

  1. W pakiecie dessertclicker utwórz nową klasę Kotlin o nazwie ClickerApplication. Aby to zrobić, rozwiń sekcję app > java i kliknij prawym przyciskiem myszy com.example.android.dessertclicker. Wybierz New > Kotlin File/Class.
  2. Nazwij klasę ClickerApplication i ustaw Kind na Class. Kliknij OK.

Android Studio utworzy nową klasę ClickerApplication i otworzy ją w edytorze kodu. Wygląda on tak:

package com.example.android.dessertclicker

class ClickerApplication {
}
  1. Zmień definicję klasy na podklasę Application i w razie potrzeby zaimportuj klasę Application.
class ClickerApplication : Application() {
  1. Aby zastąpić metodę onCreate(), wybierz Kod > Zastąp metody lub naciśnij Control+o.
class ClickerApplication : Application() {
   override fun onCreate() {
       super.onCreate()
   }
}
  1. W metodzie onCreate() zainicjuj bibliotekę Timber:
override fun onCreate() {
    super.onCreate()

    Timber.plant(Timber.DebugTree())
}

Ten wiersz kodu inicjuje bibliotekę Timber Twojej aplikacji, dzięki czemu możesz ją używać w swoich działaniach.

  1. Otwórz plik AndroidManifest.xml.
  2. U góry elementu <application> dodaj nowy atrybut klasy ClickerApplication, aby wskazać, że Android ma użyć klasy Application zamiast domyślnej.
<application
   android:name=".ClickerApplication"
...

Krok 3. Dodaj instrukcje z dziennika drewna

W tym kroku zmienisz wywołania Log.i() na Timber, a potem wdrożysz logowanie dla wszystkich pozostałych metod cyklu życia.

  1. Otwórz MainActivity i przewiń do onCreate(). Zastąp Log.i() wartością Timber.i() i usuń tag dziennika.
Timber.i("onCreate called")

Podobnie jak klasa Log, Timber używa też metody i() do wysyłania wiadomości informacyjnych. W przypadku Timber nie musisz dodawać tagu logu. Timber automatycznie używa nazwy klasy jako tagu logu.

  1. Podobnie zmień wywołanie Log w onStart():
override fun onStart() {
   super.onStart()

   Timber.i("onStart Called")
}
  1. Skompiluj i uruchom aplikację DessertClicker, a następnie otwórz aplikację Logcat. Zauważ, że nadal widzisz te same komunikaty dziennika dla onCreate() i onStart(), ale teraz powoduje to Timbergenerowanie tych wiadomości, a nie klasę Log.
  2. Zastąp pozostałe metody cyklu życia w MainActivity i dodaj instrukcje Timber dla każdej z nich. Oto kod:
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. Ponownie skompiluj i uruchom narzędzie DessertClicker, a następnie sprawdź narzędzie Logcat. Tym razem zauważysz, że oprócz onCreate() i onStart() występuje też komunikat dziennika wywołania zwrotnego cyklu życia onResume().

Gdy aktywność zaczyna się od zera, wyświetlane są wszystkie 3 wywołania zwrotne cyklu życia, które są wywoływane w określonej kolejności:

  • onCreate(), aby utworzyć aplikację.
  • onStart(), aby go włączyć i wyświetlić na ekranie.
  • onResume(), aby skupić aktywność i przygotować się na interakcję użytkownika.

Pomimo tej nazwy metoda onResume() jest wywoływana podczas uruchamiania, nawet jeśli nie ma nic do wznowienia.

Teraz gdy aplikacja DessertClicker jest skonfigurowana do logowania, możesz zacząć korzystać z aplikacji na różne sposoby i zobaczyć, jak wywołania zwrotne cyklu życia są wywoływane w odpowiedzi na te zastosowania.

Przypadek użycia 1. Otwieranie i zamykanie aktywności

Zacznij od najbardziej podstawowego przypadku, czyli uruchomienia aplikacji po raz pierwszy, a potem jej zamknięcia.

  1. Jeśli jeszcze nie została uruchomiona, skompiluj i uruchom aplikację DessertClicker. Jak widzisz, wywołania zwrotne onCreate(), onStart() i onResume() są wywoływane podczas pierwszego działania.
  2. Kilka razy kliknij babeczkę.
  3. Kliknij przycisk Wstecz na urządzeniu. Zanotuj w dzienniku Logcat, że elementy onPause(), onStop() i onDestroy() są wywoływane w tej kolejności.

    W tym przypadku użycie przycisku Wstecz powoduje całkowite zamknięcie aktywności (i aplikacji). Realizacja metody onDestroy() oznacza, że aktywność została całkowicie zamknięta i może być zebrana z pamięci. Czyszczenie fragmentów dotyczy automatycznego czyszczenia obiektów, których już nie używasz. Po wywołaniu onDestroy() system operacyjny wie, że te zasoby można odrzucić, i zaczyna czyścić pamięć.

    Aktywność może też zostać całkowicie zamknięta, jeśli kod ręcznie wywoła metodę aktywności finish() lub gdy użytkownik wymusza zamknięcie aplikacji (na przykład użytkownik może wymusić zamknięcie aplikacji na ekranie Ostatnie kliknięcie, klikając X w rogu okna). System Android może również samodzielnie wyłączyć Twoją aktywność, jeśli aplikacja nie pojawi się na ekranie przez dłuższy czas. Pozwala to na wykorzystanie baterii i umożliwienie aplikacji wykorzystania zasobów przez inne aplikacje.
  4. Użyj ekranu Ostatnie, by wrócić do aplikacji. Oto logcat:


    Aktywność została zniszczona w poprzednim kroku, więc gdy wrócisz do aplikacji, Android uruchomi nową aktywność i wywoła metody onCreate(), onStart() i onResume(). Zwróć uwagę, że żadne statystyki DessertClicker z poprzedniej aktywności nie zostały zachowane.

    Ważne jest, aby elementy onCreate() i onDestroy() były wywoływane tylko raz w danym momencie aktywności: onCreate() do inicjowania aplikacji po raz pierwszy, a onDestroy() do oczyszczenia zasobów wykorzystywanych w aplikacji.

    Metoda onCreate() jest ważnym krokiem na tym etapie. Tutaj odbywa się pierwsze uruchomienie procesu, w którym konfigurujesz układ po raz pierwszy, czyli za pomocą ciśnienia, a także w miejscu inicjowania zmiennych.

Przypadek użycia 2. Powrót do aktywności i jej powrót

Teraz, gdy aplikacja została uruchomiona i zamknięta, większość stanów cyklu życia została wyświetlona, gdy aktywność została utworzona po raz pierwszy. Otrzymujesz też informacje o całym cyklu życia, według którego aktywność jest przeprowadzana po całkowitym zamknięciu i zniszczeniu. Jednak w trakcie korzystania z urządzeń z Androidem użytkownicy przełączają się między aplikacjami, wracają do domu, uruchamiają nowe aplikacje i zajmują się innymi czynnościami, takimi jak rozmowy telefoniczne.

Twoja aktywność nie zamyka się za każdym razem, gdy użytkownik opuści daną aktywność:

  • Jeśli aktywność nie jest już widoczna na ekranie, nazywamy to umieszczeniem w tle. (przeciwieństwem jest aktywność na pierwszym planie lub na ekranie).
  • Gdy użytkownik wróci do aplikacji, ta sama aktywność zostanie zrestartowana i ponownie stanie się widoczna. Ta część cyklu życia jest nazywana widocznym cyklem życia aplikacji.

Gdy aplikacja działa w tle, nie powinna być aktywna, aby oszczędzać zasoby systemowe i baterię. Cykl życia Activity i jego wywołania zwrotne pozwalają sprawdzić, kiedy aplikacja działa w tle. Dzięki temu możesz wstrzymać trwające operacje. Potem ponownie uruchamiasz operacje, gdy aplikacja działa na pierwszym planie.

Załóżmy np., że masz aplikację, która przeprowadza symulację fizyki. Aby ustalić, gdzie powinny znaleźć się wszystkie obiekty i wyświetlić je, procesor wymaga wielu obliczeń. Jeśli połączenie telefoniczne przerywa symulację, użytkownik może być zdezorientowany, a nawet zdenerwowany, aby wrócić do aplikacji i zobaczyć, że symulacja została zakończona.

Jest to również spowodowane wydajnością. Załóżmy, że użytkownik otworzył 20 aplikacji, które korzystają z symulacji fizyki opartej na wykorzystaniu procesora. Jeśli te aplikacje nie wyświetlają się na ekranie, ale w tle wciąż wykonują intensywne obliczenia w tle, może to zmniejszyć wydajność całego telefonu.

W tym kroku sprawdzisz cykl życia aktywności, gdy aplikacja działa w tle, i wraca na pierwszy plan.

  1. Po uruchomieniu aplikacji DessertClicker kilka razy kliknij babeczkę.
  2. Naciśnij przycisk ekranu głównego na swoim urządzeniu i obserwuj aplikację Logcat w Android Studio. Powrót do ekranu głównego powoduje uruchomienie aplikacji w tle, a nie jej wyłączenie. Zwróć uwagę, że wywoływana jest metoda onPause() i metoda onStop(), ale onDestroy() nie.


    Po wywołaniu onPause() aplikacja nie jest już aktywna. Po onStop() aplikacja nie będzie już widoczna na ekranie. Choć aktywność została zatrzymana, obiekt Activity jest nadal w pamięci w tle. Aktywność nie została zniszczona. Użytkownik może wrócić do aplikacji, więc Android pozostawi zasób aktywności.
  3. Użyj ekranu Ostatnie, by wrócić do aplikacji. Zwróć uwagę w usłudze Logcat, że aktywność została ponownie uruchomiona z onRestart() i onStart(), a następnie wznowiona za pomocą onResume().


    Kiedy aktywność wróci na pierwszym planie, metoda onCreate() nie zostanie wywołana ponownie. Obiekt aktywności nie został zniszczony, więc nie trzeba go tworzyć ponownie. Zamiast onCreate() wywoływana jest metoda onRestart(). Za każdym razem, gdy aktywność wróci na pierwszym planie, liczba sprzedanych deserów zostanie zachowana.
  4. Uruchom przynajmniej jedną aplikację inną niż DessertClicker, aby na ekranie ostatnio używanych było kilka aplikacji.
  5. Wyświetl ekran ostatnich i przejdź do ostatniej aktywności. Następnie wróć do ostatnich aplikacji i spraw, aby DessertClicker znalazła się na pierwszym planie.

    Tutaj widzisz te same wywołania zwrotne w LogCat, gdy naciśniesz przycisk ekranu głównego. Aplikacje onPause() i onStop() są wywoływane, gdy aplikacja działa w tle. Następnie onRestart(), onStart() i onResume(), gdy wraca.

    Ważne jest, aby elementy onStart() i onStop() były wywoływane wiele razy, gdy użytkownik przechodzi do danej aktywności i z niej korzysta. Należy zastąpić te metody, aby zatrzymać aplikację, gdy porusza się w tle, lub uruchomić ją ponownie, gdy wróci na pierwszym planie.

    A co z onRestart()? Metoda onRestart() przypomina onCreate(). Aby aktywność była widoczna, należy wywołać onCreate() lub onRestart(). Metoda onCreate() jest wywoływana tylko po raz pierwszy, a kolejna onRestart() jest wywoływana. Metoda onRestart() to miejsce, w którym chcesz umieścić kod, który będzie wywoływany tylko wtedy, gdy Twoja aktywność nie jest rozpoczynana.

Przypadek użycia 3. Częściowe ukrycie aktywności

Dowiedz się, że gdy aplikacja zostanie uruchomiona, a Ty wywołasz onStart(), pojawi się ona na ekranie. Gdy aplikacja zostanie wznowiona, a onResume() zostanie wywołana, skupi się na użytkowniku. Część cyklu życia, w której aplikacja jest w pełni widoczna na ekranie, i skoncentrowana na użytkownikach, jest nazywana interaktywnym.

Gdy aplikacja przejdzie w tle, po onPause() straci ona ważność, a aplikacja przestanie być widoczna po onStop().

Różnica między ostrości a widocznością jest ważna, ponieważ aktywność może być częściowo widoczna na ekranie, ale nie może być skupiona na użytkowniku. W tym kroku przyjrzysz się pojedynczemu działaniu, które jest częściowo widoczne, ale nie skupia się na użytkowniku.

  1. Po włączeniu aplikacji DessertClicker kliknij przycisk Udostępnij w prawym górnym rogu ekranu.




    Aktywność związana z udostępnianiem jest widoczna w dolnej połowie ekranu, ale nadal pojawia się w jej górnej części.
  2. Zbadaj logcat i zauważ, że wywołano tylko element onPause().


    W tym przypadku element onStop() nie jest wywoływany, ponieważ aktywność jest nadal częściowo widoczna. Aktywność nie jest jednak skupiona na użytkowniku i nie może z niej korzystać. Aktywność użytkownika dotycząca udostępniania na pierwszym planie jest ukierunkowana na użytkowników.

    Dlaczego ta różnica jest ważna? Rozważ uruchomienie aplikacji do fizyki. Możesz zasygnalizować zakończenie symulacji, gdy aplikacja działa w tle, i kontynuować jej pracę, gdy aplikacja jest częściowo zasłonięta. W takim przypadku symulację trzeba będzie zatrzymać w onStop(). Jeśli chcesz zatrzymać symulację, gdy aktywność jest częściowo zasłonięta, umieść ten kod na stronie onPause().

    Bez względu na to, który kod działa w onPause(), inne elementy nie będą się wyświetlać. Dlatego lepiej unikać wyświetlania kodu onPause(). Jeśli na przykład ktoś do Ciebie dzwoni, kod w parametrze onPause() może opóźnić połączenie.
  3. Kliknij ponownie poza oknem udostępniania, by powrócić do aplikacji, i sprawdź, że wywołano onResume().

    Obie usługi onResume() i onPause() muszą się skupić. Metoda onResume() jest wywoływana, gdy aktywność jest aktywna, a onPause() jest wywoływana, gdy aktywność traci skupienie.

Cykl życia fragmentu na Androidzie jest podobny do cyklu życia aktywności oraz kilku metod działania dla tego fragmentu.

W tym zadaniu patrzysz na aplikację AndroidTrivia utworzoną w poprzednich ćwiczeniach z programowania i dodajesz logi, aby poznać cykl życia fragmentu. Aplikacja AndroidTrivia umożliwia Ci odpowiadanie na pytania dotyczące programowania na Androida. Jeśli odpowiesz prawidłowo na trzy pytania z rzędu, wygrasz grę.

Każdy ekran w aplikacji AndroidTrivia to Fragment.

Dla uproszczenia użyj w tym zadaniu interfejsu Android Logging API, a nie biblioteki Timber.

  1. Otwórz aplikację AndroidTrivia z ostatniego ćwiczenia z programowania lub pobierz kod rozwiązania AndroidTrivia z GitHuba.
  2. Otwórz plik TitleFragment.kt. Pamiętaj, że Android Studio może wyświetlać błędy powiązania i nierozwiązane problemy z plikami referencyjnymi, dopóki ponownie nie utworzysz aplikacji.
  3. Przewiń w dół do metody onCreateView(). Zwróć uwagę, że w tym przypadku układ fragmentu jest zawyżony i występują wiązania danych.
  4. Dodaj instrukcję logowania do metody onCreateView(), między wierszem setHasOptionsMenu() a ostatecznym wywołaniem, które ma zostać zwrócone:
setHasOptionsMenu(true)

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

return binding.root
  1. Tuż pod metodą onCreateView() dodaj instrukcje logowania do każdej z pozostałych metod cyklu życia fragmentu. Oto kod:
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. Skompiluj i uruchom aplikację, a następnie otwórz aplikację Logcat.
  2. Aby przefiltrować dziennik, wpisz I/TitleFragment w polu wyszukiwania. Po uruchomieniu aplikacji Logcat będzie wyglądać mniej więcej tak jak na tym zrzucie ekranu:

Tutaj możesz zobaczyć cały cykl życia uruchamiania fragmentu, w tym te wywołania zwrotne:

  • onAttach(): element jest wywoływany, gdy fragment jest powiązany z aktywnością właściciela.
  • onCreate(): podobnie jak onCreate() w przypadku aktywności, we właściwości onCreate() jest wywoływany początkowy fragment (inny niż układ).
  • onCreateView(): wywołano zawyżenie układu fragmentu.
  • onActivityCreated(): wywoływane po zakończeniu działania właściciela onCreate(). Twój fragment nie będzie miał dostępu do aktywności do momentu wywołania tej metody.
  • onStart(): wywoływane, gdy fragment stanie się widoczny; równolegle do aktywności onStart().
  • onResume(): wywoływane, gdy fragment uzyska priorytet użytkownika. Równolegle do aktywności onResume().
  1. Kliknij przycisk Zagraj, aby przejść do quizu, a zobaczysz aplikację Logcat.

Otwarcie następnego fragmentu powoduje zamknięcie fragmentu tytułu i wywołanie tych metod cyklu życia:

  • onPause(): wywoływane, gdy fragment straci aktywność użytkownika. Równolegle do aktywności onPause().
  • onStop(): wywoływane, gdy fragment nie jest już widoczny na ekranie. Równolegle do aktywności onStop().
  • onDestroyView(): element jest wywoływany, gdy widok fragmentu nie jest już potrzebny, aby wyczyścić zasoby powiązane z tym widokiem.
  1. W aplikacji kliknij przycisk ze strzałką w górę (w lewym górnym rogu ekranu), by wrócić do fragmentu tytułu.


    tym razem prawdopodobnie onAttach() i onCreate() nie muszą wywoływać fragmentu. Obiekt fragmentu nadal istnieje i jest powiązany z aktywnością właściciela, dlatego cykl życia zaczyna się ponownie od onCreateView().
  2. Naciśnij przycisk ekranu głównego urządzenia. W dzienniku Logcat pojawi się informacja, że wywoływane są tylko onPause() i onStop(). Jest to takie samo działanie jak w przypadku aktywności – po powrocie do domu aktywność i fragment pojawiają się w tle.
  3. Użyj ekranu Ostatnie, by wrócić do aplikacji. Tak jak w przypadku aktywności, wywoływane są metody onStart() i onResume(), by przywrócić fragment na pierwszym planie.

Projekt na Android Studio: DessertClickerLogs

Cykl życia aktywności

  • Cykl życia aktywności to zestaw stanów, w których następuje migracja aktywności. Cykl życia aktywności rozpoczyna się w momencie jej utworzenia i kończy w przypadku jej zniszczenia.
  • Gdy użytkownik przechodzi między aktywnością oraz w aplikacji i poza nią, każde działanie przemieszcza się między stanami w cyklu życia aktywności.
  • Każdy stan w cyklu życia aktywności ma odpowiednią metodę wywołania zwrotnego, którą możesz zastąpić w klasie Activity. Istnieje 7 metod cyklu życia:
    onCreate()
    onStart()
    onPause()
    onRestart()
    onResume()
    onStop()
    onDestroy()
  • Aby dodać zachowanie, które następuje, gdy aktywność zmienia się w stan cyklu życia, zastąp metodę wywołania zwrotnego stanu.
  • Aby dodać szkielet metod zastępowania do zajęć w Android Studio, wybierz Kod > Zastąp metody lub naciśnij Control+o.

Rejestrowanie przy użyciu dziennika

  • Interfejs Android Logging API, a w szczególności klasy Log, pozwala pisać krótkie wiadomości wyświetlane w Logcat w Android Studio.
  • Użyj Log.i(), aby napisać wiadomość informacyjną. Ta metoda przyjmuje 2 argumenty: tag dziennika, zwykle nazwę klasy i komunikat z dziennika.
  • Korzystając z panelu Logcat w Android Studio, możesz wyświetlić dzienniki systemowe wraz z wpisanymi przez siebie wiadomościami.

Rejestrowanie za pomocą drewna

Timber to biblioteka dzienników, która ma kilka zalet w porównaniu z interfejsem Android Logging API. Biblioteka Timber:

  • Generuje tag dziennika na podstawie nazwy klasy.
  • Pomaga uniknąć wyświetlania dzienników w aktualnej wersji aplikacji na Androida.
  • Umożliwia integrację z bibliotekami raportowania awarii.

Aby użyć tagu Timber, dodaj jego zależność do pliku Gradle, a następnie rozszerz klasę Application, aby go zainicjować:

  • Application to klasa podstawowa, która zawiera stan aplikacji globalnej dla całej aplikacji. Istnieje domyślna klasa Application, której Android używa, jeśli jej nie określisz. Możesz utworzyć własną klasę podrzędną Application, aby inicjować biblioteki obejmujące całą aplikację, na przykład Timber.
  • Dodaj do aplikacji niestandardową klasę Application, dodając atrybut android:name do elementu <application> w pliku manifestu Androida. Nie zapomnij o tym!
  • Timber.i() pozwala pisać wiadomości dziennika w Timber. Ta metoda wymaga tylko jednego argumentu: zapisanie wiadomości. Tag dziennika (nazwa klasy) zostanie dodany automatycznie.

Kurs Udacity:

Dokumentacja dla programistów Androida:

Inne:

Ta sekcja zawiera listę możliwych zadań domowych dla uczniów, którzy pracują w ramach tego ćwiczenia w ramach kursu prowadzonego przez nauczyciela. To nauczyciel może wykonać te czynności:

  • W razie potrzeby przypisz zadanie domowe.
  • Poinformuj uczniów, jak przesyłać zadania domowe.
  • Oceń projekty domowe.

Nauczyciele mogą wykorzystać te sugestie tak długo, jak chcą lub chcą, i mogą przypisać dowolne zadanie domowe.

Jeśli samodzielnie wykonujesz te ćwiczenia z programowania, możesz sprawdzić swoją wiedzę w tych zadaniach domowych.

Zmienianie aplikacji

Otwórz aplikację DiceRoller z lekcji 1. (Jeśli nie masz aplikacji DiceRoller, możesz ją pobrać tutaj). Dodaj do tej aplikacji obsługę Timber, korzystając z tej samej procedury co w aplikacji DessertClicker. Zastąp wszystkie wywołania zwrotne cyklu życia i dodaj komunikaty logu dla każdego wywołania zwrotnego.

Odpowiedz na te pytania

Pytanie 1

Który z poniższych elementów NIE jest stanem cyklu życia aktywności?

  • Rozpoczęto
  • Czekam
  • Utworzono
  • Zniszczono

Pytanie 2

Jaka metoda cyklu życia jest wywoływana, aby aktywność była widoczna?

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

Pytanie 3

Która metoda cyklu życia jest wywoływana, aby skupić uwagę na aktywności?

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

Pytanie 4

Kiedy funkcja onCreate() jest wywoływana w ramach aktywności?

  • Za każdym razem, gdy aktywność jest widoczna dla użytkownika.
  • Za każdym razem, gdy aktywność wróci w tle.
  • Tylko raz podczas tworzenia aktywności.
  • Tylko raz, gdy aktywność zostanie wznowiona.

Przesyłanie aplikacji do oceny

Upewnij się, że aplikacja zawiera:

  • Zależność od Timber w pliku build.gradle aplikacji.
  • Niestandardowa podklasa Application, która inicjuje Timber w onCreate().
  • Atrybut klasy podrzędnej w pliku manifestu Androida.
  • Zastąpienie metody w MainActivity dla wszystkich metod wywołania cyklu życia z wywołaniami Timber.i() do logowania.

Rozpocznij następną lekcję: 4.2: złożone cykle życia cyklu

Linki do innych ćwiczeń z programowania w tym kursie znajdziesz na stronie docelowej z ćwiczeniami z podstaw Androida Kotlin.