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
iFragment
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.
- Pobierz aplikację DessertClicker starter i otwórz ją w Android Studio.
- 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.
- 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.
- W metodzie
onCreate()
tuż po wywołaniu funkcjisuper.onCreate()
dodaj ten wiersz. W razie potrzeby zaimportuj klasęLog
. (NaciśnijAlt+Enter
lubOption+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 klasyLog
toLog.e()
w przypadku błędów iLog.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"
.
- 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 metodyLog.i()
lub innych metod klasyLog
. - 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żytyMainActivity
, możesz użyć tego tagu do filtrowania dziennika. DodanieI/
na początku oznacza, że został utworzony przezLog.i()
.
Wiadomość zawiera datę i godzinę, nazwę pakietu (com.example.android.dessertclicker
), tag logu (zI/
na początku) i rzeczywisty komunikat. Ten komunikat pojawia się w dzienniku, więc wiesz, że polecenieonCreate()
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.
- W Androidzie Studio z otwartą aplikacją
MainActivity.kt
wybierz Kod > Zastąp metody lub naciśnijControl+o
. Pojawi się okno z listą wszystkich metod, które możesz zastąpić w tych zajęciach. - Zacznij wpisywać
onStart
, aby wyszukać właściwą metodę. Aby przewinąć do następnego pasującego elementu, użyj strzałki w dół. WybierzonStart()
z listy i kliknij OK, aby wstawić powtarzalny kod zastąpienia. Wygląda on tak:
override fun onStart() {
super.onStart()
}
- W metodzie
onStart()
dodaj komunikat logu:
override fun onStart() {
super.onStart()
Log.i("MainActivity", "onStart Called")
}
- 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()
ionStart()
– zostały wywołane po drugiej, a Twoja aktywność jest widoczna na ekranie. - 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 metodaonCreate()
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
- 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'
- W Android Studio w projekcie Android: rozwiń Gradle Scripts i otwórz plik build.gradle (Module: app).
- W sekcji zależności wklej skopiowany wiersz kodu.
dependencies {
...
implementation 'com.jakewharton.timber:timber:4.7.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.
- W pakiecie
dessertclicker
utwórz nową klasę Kotlin o nazwieClickerApplication
. Aby to zrobić, rozwiń sekcję app > java i kliknij prawym przyciskiem myszy com.example.android.dessertclicker. Wybierz New > Kotlin File/Class. - 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 {
}
- Zmień definicję klasy na podklasę
Application
i w razie potrzeby zaimportuj klasęApplication
.
class ClickerApplication : Application() {
- Aby zastąpić metodę
onCreate()
, wybierz Kod > Zastąp metody lub naciśnijControl+o
.
class ClickerApplication : Application() {
override fun onCreate() {
super.onCreate()
}
}
- 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.
- Otwórz plik AndroidManifest.xml.
- U góry elementu
<application>
dodaj nowy atrybut klasyClickerApplication
, aby wskazać, że Android ma użyć klasyApplication
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.
- Otwórz
MainActivity
i przewiń doonCreate()
. ZastąpLog.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.
- Podobnie zmień wywołanie
Log
wonStart()
:
override fun onStart() {
super.onStart()
Timber.i("onStart Called")
}
- Skompiluj i uruchom aplikację DessertClicker, a następnie otwórz aplikację Logcat. Zauważ, że nadal widzisz te same komunikaty dziennika dla
onCreate()
ionStart()
, ale teraz powoduje toTimber
generowanie tych wiadomości, a nie klasęLog
. - Zastąp pozostałe metody cyklu życia w
MainActivity
i dodaj instrukcjeTimber
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")
}
- Ponownie skompiluj i uruchom narzędzie DessertClicker, a następnie sprawdź narzędzie Logcat. Tym razem zauważysz, że oprócz
onCreate()
ionStart()
występuje też komunikat dziennika wywołania zwrotnego cyklu życiaonResume()
.
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.
- Jeśli jeszcze nie została uruchomiona, skompiluj i uruchom aplikację DessertClicker. Jak widzisz, wywołania zwrotne
onCreate()
,onStart()
ionResume()
są wywoływane podczas pierwszego działania. - Kilka razy kliknij babeczkę.
- Kliknij przycisk Wstecz na urządzeniu. Zanotuj w dzienniku Logcat, że elementy
onPause()
,onStop()
ionDestroy()
są wywoływane w tej kolejności.
W tym przypadku użycie przycisku Wstecz powoduje całkowite zamknięcie aktywności (i aplikacji). Realizacja metodyonDestroy()
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łaniuonDestroy()
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ścifinish()
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. - 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 metodyonCreate()
,onStart()
ionResume()
. Zwróć uwagę, że żadne statystyki DessertClicker z poprzedniej aktywności nie zostały zachowane.
Ważne jest, aby elementyonCreate()
ionDestroy()
były wywoływane tylko raz w danym momencie aktywności:onCreate()
do inicjowania aplikacji po raz pierwszy, aonDestroy()
do oczyszczenia zasobów wykorzystywanych w aplikacji.
MetodaonCreate()
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.
- Po uruchomieniu aplikacji DessertClicker kilka razy kliknij babeczkę.
- 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 metodaonStop()
, aleonDestroy()
nie.
Po wywołaniuonPause()
aplikacja nie jest już aktywna. PoonStop()
aplikacja nie będzie już widoczna na ekranie. Choć aktywność została zatrzymana, obiektActivity
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. - Użyj ekranu Ostatnie, by wrócić do aplikacji. Zwróć uwagę w usłudze Logcat, że aktywność została ponownie uruchomiona z
onRestart()
ionStart()
, a następnie wznowiona za pomocąonResume()
.
Kiedy aktywność wróci na pierwszym planie, metodaonCreate()
nie zostanie wywołana ponownie. Obiekt aktywności nie został zniszczony, więc nie trzeba go tworzyć ponownie. ZamiastonCreate()
wywoływana jest metodaonRestart()
. Za każdym razem, gdy aktywność wróci na pierwszym planie, liczba sprzedanych deserów zostanie zachowana. - Uruchom przynajmniej jedną aplikację inną niż DessertClicker, aby na ekranie ostatnio używanych było kilka aplikacji.
- 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. AplikacjeonPause()
ionStop()
są wywoływane, gdy aplikacja działa w tle. NastępnieonRestart()
,onStart()
ionResume()
, gdy wraca.
Ważne jest, aby elementyonStart()
ionStop()
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 zonRestart()
? MetodaonRestart()
przypominaonCreate()
. Aby aktywność była widoczna, należy wywołaćonCreate()
lubonRestart()
. MetodaonCreate()
jest wywoływana tylko po raz pierwszy, a kolejnaonRestart()
jest wywoływana. MetodaonRestart()
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.
- 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. - Zbadaj logcat i zauważ, że wywołano tylko element
onPause()
.
W tym przypadku elementonStop()
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ć wonStop()
. Jeśli chcesz zatrzymać symulację, gdy aktywność jest częściowo zasłonięta, umieść ten kod na stronieonPause()
.
Bez względu na to, który kod działa wonPause()
, inne elementy nie będą się wyświetlać. Dlatego lepiej unikać wyświetlania koduonPause()
. Jeśli na przykład ktoś do Ciebie dzwoni, kod w parametrzeonPause()
może opóźnić połączenie. - Kliknij ponownie poza oknem udostępniania, by powrócić do aplikacji, i sprawdź, że wywołano
onResume()
.
Obie usługionResume()
ionPause()
muszą się skupić. MetodaonResume()
jest wywoływana, gdy aktywność jest aktywna, aonPause()
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.
- Otwórz aplikację AndroidTrivia z ostatniego ćwiczenia z programowania lub pobierz kod rozwiązania AndroidTrivia z GitHuba.
- 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. - Przewiń w dół do metody
onCreateView()
. Zwróć uwagę, że w tym przypadku układ fragmentu jest zawyżony i występują wiązania danych. - Dodaj instrukcję logowania do metody
onCreateView()
, między wierszemsetHasOptionsMenu()
a ostatecznym wywołaniem, które ma zostać zwrócone:
setHasOptionsMenu(true)
Log.i("TitleFragment", "onCreateView called")
return binding.root
- 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")
}
- Skompiluj i uruchom aplikację, a następnie otwórz aplikację Logcat.
- 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 jakonCreate()
w przypadku aktywności, we właściwościonCreate()
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ścicielaonCreate()
. 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ścionStart()
.onResume()
: wywoływane, gdy fragment uzyska priorytet użytkownika. Równolegle do aktywnościonResume()
.
- 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ścionPause()
.onStop()
: wywoływane, gdy fragment nie jest już widoczny na ekranie. Równolegle do aktywnościonStop()
.onDestroyView()
: element jest wywoływany, gdy widok fragmentu nie jest już potrzebny, aby wyczyścić zasoby powiązane z tym widokiem.
- 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 prawdopodobnieonAttach()
ionCreate()
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 odonCreateView()
. - Naciśnij przycisk ekranu głównego urządzenia. W dzienniku Logcat pojawi się informacja, że wywoływane są tylko
onPause()
ionStop()
. Jest to takie samo działanie jak w przypadku aktywności – po powrocie do domu aktywność i fragment pojawiają się w tle. - Użyj ekranu Ostatnie, by wrócić do aplikacji. Tak jak w przypadku aktywności, wywoływane są metody
onStart()
ionResume()
, 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 klasaApplication
, 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ładTimber
.- Dodaj do aplikacji niestandardową klasę
Application
, dodając atrybutandroid:name
do elementu<application>
w pliku manifestu Androida. Nie zapomnij o tym! Timber.i()
pozwala pisać wiadomości dziennika wTimber
. Ta metoda wymaga tylko jednego argumentu: zapisanie wiadomości. Tag dziennika (nazwa klasy) zostanie dodany automatycznie.
Kurs Udacity:
Dokumentacja dla programistów Androida:
- Działania (przewodnik po interfejsie API)
- Fragmenty (przewodnik po interfejsie API)
Activity
(odniesienie do interfejsu API)Fragment
(odniesienie do interfejsu API)- Omówienie cyklu życia aktywności
- Zapisywanie i wyświetlanie logów przy użyciu LogCat
Log
(odniesienie do interfejsu API)
Inne:
- Timber (GitHub)
- Ściągawka dotycząca cyklu życia Androida – część I: Pojedyncze działania to wizualne podsumowanie znacznej części materiału.
- Ściągawka dotycząca cyklu życia Androida – część II: Wiele działań pokazuje kolejność wywołań cyklu życia, gdy istnieją 2 interakcje.
- Ściągawka dotycząca cyklu życia Androida – część III: Fragmenty pokazuje kolejność wywołań cyklu życia, gdy aktywność i fragment kodu współdziałają z użytkownikiem.
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 plikubuild.gradle
aplikacji. - Niestandardowa podklasa
Application
, która inicjujeTimber
wonCreate()
. - Atrybut klasy podrzędnej w pliku manifestu Androida.
- Zastąpienie metody w
MainActivity
dla wszystkich metod wywołania cyklu życia z wywołaniamiTimber.i()
do logowania.
Rozpocznij następną lekcję:
Linki do innych ćwiczeń z programowania w tym kursie znajdziesz na stronie docelowej z ćwiczeniami z podstaw Androida Kotlin.