1. Velkommen
Dette praktiske codelab er en del af Unit 1: Kom godt i gang med Android Developer Fundamentals (Version 2)-kurset. Du vil få mest muligt ud af dette kursus, hvis du arbejder gennem codelabs i rækkefølge:
- For den komplette liste over codelabs i kurset, se Codelabs for Android Developer Fundamentals (V2).
- For detaljer om kurset, inklusive links til alle konceptkapitlerne, apps og slides, se Android Developer Fundamentals (version 2).
Indledning
I denne praktik lærer du mere om aktivitetens livscyklus. Livscyklussen er det sæt af tilstande, en aktivitet kan befinde sig i i hele sin levetid, fra den er oprettet, til den bliver ødelagt, og systemet genvinder sine ressourcer. Når en bruger navigerer mellem aktiviteter i din app (såvel som ind og ud af din app), skifter aktiviteter mellem forskellige tilstande i deres livscyklus.
Hvert trin i en aktivitets livscyklus har en tilsvarende tilbagekaldsmetode: onCreate(), onStart(), onPause() og så videre. Når en aktivitet ændrer tilstand, aktiveres den tilknyttede tilbagekaldsmetode. Du har allerede set en af disse metoder: onCreate(). Ved at tilsidesætte en af livscyklus-tilbagekaldsmetoderne i dine aktivitetsklasser kan du ændre aktivitetens standardadfærd som svar på bruger- eller systemhandlinger.
Aktivitetstilstanden kan også ændre sig som reaktion på enhedskonfigurationsændringer, for eksempel når brugeren roterer enheden fra portræt til landskab. Når disse konfigurationsændringer sker, ødelægges aktiviteten og genskabes i sin standardtilstand, og brugeren kan miste oplysninger, som de har indtastet i aktiviteten. For at undgå at forvirre dine brugere, er det vigtigt, at du udvikler din app for at forhindre uventet datatab. Senere i denne praktik eksperimenterer du med konfigurationsændringer og lærer, hvordan du bevarer en aktivitets tilstand som reaktion på enhedskonfigurationsændringer og andre aktivitetslivscyklushændelser.
I denne praktiske øvelse tilføjer du logningserklæringer til TwoActivities-appen og observerer ændringer i aktivitetens livscyklus, mens du bruger appen. Du begynder derefter at arbejde med disse ændringer og undersøge, hvordan du håndterer brugerinput under disse forhold.
Forudsætninger
Du skal kunne:
- Opret og kør et app-projekt i Android Studio .
- Tilføj logerklæringer til din app, og se disse logfiler i Logcat-ruden.
- Forstå og arbejde med en aktivitet og en hensigt, og vær komfortabel med at interagere med dem.
Hvad du vil lære
- Sådan fungerer aktivitetens livscyklus.
- Når en aktivitet starter, pauser, stopper og ødelægges.
- Om de livscyklus-tilbagekaldsmetoder, der er forbundet med aktivitetsændringer.
- Effekten af handlinger (såsom konfigurationsændringer), der kan resultere i aktivitetslivscyklushændelser.
- Sådan bevarer du aktivitetstilstand på tværs af livscyklushændelser.
Hvad du vil gøre
- Tilføj kode til TwoActivities -appen fra den forrige praktiske for at implementere de forskellige aktivitets-livscyklus-tilbagekald for at inkludere logningserklæringer.
- Observer tilstandsændringerne, mens din app kører, og når du interagerer med hver aktivitet i din app.
- Rediger din app for at bevare forekomsttilstanden for en aktivitet, der uventet genskabes som reaktion på brugeradfærd eller konfigurationsændringer på enheden.
2. App oversigt
I denne praktiske tilføjelse tilføjer du TwoActivities -appen. Appen ser ud og opfører sig nogenlunde det samme, som den gjorde i det sidste codelab. Den indeholder to Activity-implementeringer og giver brugeren mulighed for at sende mellem dem. De ændringer, du foretager i appen i denne praktiske, vil ikke påvirke dens synlige brugeradfærd.
3. 3. Opgave 1: Tilføj livscyklustilbagekald til TwoActivities
I denne opgave vil du implementere alle Aktivitets livscyklus-tilbagekaldsmetoder for at udskrive meddelelser til logcat, når disse metoder påkaldes. Disse logmeddelelser giver dig mulighed for at se, hvornår aktivitetens livscyklus ændrer tilstand, og hvordan disse ændringer i livscyklustilstanden påvirker din app, mens den kører.
1.1 (Valgfrit) Kopier TwoActivities-projektet
Til opgaverne i denne praktik, vil du ændre det eksisterende TwoActivities -projekt, du byggede i den sidste praktik. Hvis du foretrækker at beholde det tidligere TwoActivities-projekt intakt, skal du følge trinene i Appendiks: Hjælpeprogrammer for at lave en kopi af projektet.
1.2 Implementer tilbagekald i MainActivity
- Åbn TwoActivities-projektet i Android Studio, og åbn MainActivity i panelet Projekt > Android.
- Tilføj følgende logsætninger i onCreate()-metoden:
Log.d(LOG_TAG, "-------");
Log.d(LOG_TAG, "onCreate");
- Tilføj en tilsidesættelse for onStart()-tilbagekaldet med en erklæring til loggen for den pågældende hændelse:
@Override
public void onStart(){
super.onStart();
Log.d(LOG_TAG, "onStart");
}
For en genvej skal du vælge Kode > Tilsidesæt metoder i Android Studio. Der vises en dialogboks med alle de mulige metoder, du kan tilsidesætte i din klasse. Hvis du vælger en eller flere tilbagekaldsmetoder fra listen, indsættes en komplet skabelon for disse metoder, inklusive det nødvendige kald til superklassen.
- Brug metoden onStart() som en skabelon til at implementere onPause(), onRestart(), onResume(), onStop() og onDestroy() livscyklus-tilbagekaldene
Alle tilbagekaldsmetoder har de samme signaturer (bortset fra navnet). Hvis du kopierer og indsætter onStart() for at oprette disse andre tilbagekaldsmetoder, så glem ikke at opdatere indholdet for at kalde den rigtige metode i superklassen og for at logge den korrekte metode.
- Kør din app.
- Klik på fanen Logcat i bunden af Android Studio for at vise Logcat-ruden. Du bør se tre log-meddelelser, der viser de tre livscyklustilstande, som aktiviteten er gået igennem, da den startede:
D/MainActivity: -------
D/MainActivity: onCreate
D/MainActivity: onStart
D/MainActivity: onResume
1.3 Implementer lifecycle callbacks i SecondActivity
Nu hvor du har implementeret livscyklus-tilbagekaldsmetoderne for MainActivity, skal du gøre det samme for SecondActivity.
- Åbn SecondActivity.
- Øverst i klassen skal du tilføje en konstant for variablen LOG_TAG:
private static final String LOG_TAG = SecondActivity.class.getSimpleName();
- Tilføj livscyklustilbagekaldene og logerklæringer til den anden aktivitet. (Du kan kopiere og indsætte tilbagekaldsmetoderne fra MainActivity.)
- Tilføj en logsætning til returnReply()-metoden lige før finish()-metoden:
Log.d(LOG_TAG, "End SecondActivity");
1.4 Observer loggen, mens appen kører**
- Kør din app.
- Klik på fanen Logcat i bunden af Android Studio for at vise Logcat-ruden.
- Indtast aktivitet i søgefeltet. Android logcat kan være meget lang og rodet. Fordi LOG_TAG-variablen i hver klasse indeholder enten ordene MainActivity eller SecondActivity, lader dette søgeord dig filtrere loggen for kun de ting, du er interesseret i.
Eksperimenter med din app, og bemærk, at de livscyklushændelser, der opstår som reaktion på forskellige handlinger. Prøv især disse ting:
- Brug appen normalt (send en besked, svar med en anden besked).
- Brug knappen Tilbage for at gå tilbage fra den anden aktivitet til hovedaktiviteten.
- Brug pil op på applinjen for at gå tilbage fra den anden aktivitet til hovedaktiviteten.
- Roter enheden på både hoved- og andenaktiviteten på forskellige tidspunkter i din app, og observer, hvad der sker i *-loggen og på skærmen.
- Tryk på oversigtsknappen (den firkantede knap til højre for Hjem), og luk appen (tryk på X).
- Vend tilbage til startskærmen og genstart din app.
TIP: Hvis du kører din app i en emulator, kan du simulere rotation med Control+F11 eller Control+Function+F11.
Opgave 1 løsningskode
Følgende kodestykker viser løsningskoden for den første opgave.
Hovedaktivitet
Følgende kodestykker viser den tilføjede kode i MainActivity, men ikke hele klassen.
OnCreate() metoden:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Log the start of the onCreate() method.
Log.d(LOG_TAG, "-------");
Log.d(LOG_TAG, "onCreate");
// Initialize all the view variables.
mMessageEditText = findViewById(R.id.editText_main);
mReplyHeadTextView = findViewById(R.id.text_header_reply);
mReplyTextView = findViewById(R.id.text_message_reply);
}
De andre livscyklusmetoder:
@Override
protected void onStart() {
super.onStart();
Log.d(LOG_TAG, "onStart");
}
@Override
protected void onPause() {
super.onPause();
Log.d(LOG_TAG, "onPause");
}
@Override
protected void onRestart() {
super.onRestart();
Log.d(LOG_TAG, "onRestart");
}
@Override
protected void onResume() {
super.onResume();
Log.d(LOG_TAG, "onResume");
}
@Override
protected void onStop() {
super.onStop();
Log.d(LOG_TAG, "onStop");
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.d(LOG_TAG, "onDestroy");
}
SecondActivity
Følgende kodestykker viser den tilføjede kode i SecondActivity, men ikke hele klassen.
Øverst i SecondActivity-klassen:
private static final String LOG_TAG = SecondActivity.class.getSimpleName();
ReturnReply() metoden:
public void returnReply(View view) {
String reply = mReply.getText().toString();
Intent replyIntent = new Intent();
replyIntent.putExtra(EXTRA_REPLY, reply);
setResult(RESULT_OK, replyIntent);
Log.d(LOG_TAG, "End SecondActivity");
finish();
}
De andre livscyklusmetoder:
Samme som for MainActivity ovenfor.
4. 4. Opgave 2: Gem og gendan tilstanden Aktivitetsforekomst
Afhængigt af systemressourcer og brugeradfærd kan hver aktivitet i din app blive ødelagt og rekonstrueret langt oftere, end du måske tror.
Du har muligvis bemærket denne adfærd i det sidste afsnit, da du roterede enheden eller emulatoren. Rotation af enheden er et eksempel på en enhedskonfigurationsændring. Selvom rotation er den mest almindelige, resulterer alle konfigurationsændringer i, at den aktuelle aktivitet bliver ødelagt og genskabt, som om den var ny. Hvis du ikke tager højde for denne adfærd i din kode, når der sker en konfigurationsændring, kan dit aktivitetslayout vende tilbage til dets standardudseende og startværdier, og dine brugere kan miste deres plads, deres data eller status for deres fremskridt i din app.
Tilstanden for hver aktivitet er gemt som et sæt nøgle/værdi-par i et bundleobjekt kaldet aktivitetsinstanstilstanden. Systemet gemmer standardtilstandsoplysninger til instanstilstandsbundt lige før aktiviteten stoppes, og sender denne bundt til den nye aktivitetsforekomst for at gendanne.
For at undgå at miste data i en aktivitet, når de uventet bliver ødelagt og genskabt, skal du implementere onSaveInstanceState()-metoden. Systemet kalder denne metode på din aktivitet (mellem onPause() og onStop()), når der er mulighed for, at aktiviteten kan blive ødelagt og genskabt.
De data, du gemmer i instanstilstanden, er kun specifikke for denne instans af denne specifikke aktivitet under den aktuelle appsession. Når du stopper og genstarter en ny app-session, går tilstanden Aktivitetsforekomst tabt, og aktiviteten vender tilbage til sit standardudseende. Hvis du har brug for at gemme brugerdata mellem app-sessioner, skal du bruge delte præferencer eller en database. Du lærer om begge disse i en senere praktik.
2.1 Gem aktivitetsforekomsttilstanden med onSaveInstanceState()
Du har måske bemærket, at rotation af enheden slet ikke påvirker tilstanden af den anden aktivitet. Dette skyldes, at det andet aktivitetslayout og -tilstand genereres ud fra layoutet og den hensigt, der aktiverede det. Selvom aktiviteten genskabes, er hensigten der stadig, og dataene i den hensigt bruges stadig, hver gang onCreate()-metoden i den anden aktivitet kaldes.
Derudover kan du bemærke, at i hver aktivitet bevares enhver tekst, du har indtastet i meddelelsen eller svar EditText-elementer, selv når enheden roteres. Dette skyldes, at tilstandsoplysningerne for nogle af View-elementerne i dit layout automatisk gemmes på tværs af konfigurationsændringer, og den aktuelle værdi af en EditText er et af disse tilfælde.
Så den eneste aktivitetstilstand, du er interesseret i, er TextView-elementerne for svaroverskriften og svarteksten i hovedaktiviteten. Begge TextView-elementer er usynlige som standard; de vises kun, når du sender en besked tilbage til hovedaktiviteten fra den anden aktivitet.
I denne opgave tilføjer du kode for at bevare instanstilstanden for disse to TextView-elementer ved hjælp af onSaveInstanceState().
- Åbn MainActivity.
- Føj denne skeletimplementering af onSaveInstanceState() til aktiviteten, eller brug Kode > Tilsidesættelsesmetoder til at indsætte en skelettilsidesættelse.
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
}
- Tjek for at se, om headeren i øjeblikket er synlig, og hvis det er tilfældet, indsæt den synlighedstilstand i tilstandspakken med putBoolean()-metoden og nøglen "reply_visible".
if (mReplyHeadTextView.getVisibility() == View.VISIBLE) {
outState.putBoolean("reply_visible", true);
}
Husk, at svaroverskriften og teksten er markeret som usynlige, indtil der er et svar fra den anden aktivitet. Hvis overskriften er synlig, så er der svardata, der skal gemmes. Bemærk, at vi kun er interesserede i denne synlighedstilstand - den faktiske tekst i overskriften behøver ikke at blive gemt, fordi den tekst aldrig ændres.
- Inden i den samme markering skal du tilføje svarteksten i pakken.
outState.putString("reply_text",mReplyTextView.getText().toString());
Hvis overskriften er synlig, kan du antage, at selve svarmeddelelsen også er synlig. Du behøver ikke at teste for eller gemme den aktuelle synlighedstilstand for svarbeskeden. Kun den faktiske tekst i beskeden går ind i tilstandspakken med nøglen "reply_text".
Du gemmer kun tilstanden for de View-elementer, der kan ændre sig, efter at aktiviteten er oprettet. De andre View-elementer i din app (Redigeringsteksten, knappen) kan til enhver tid genskabes fra standardlayoutet.
Bemærk, at systemet gemmer tilstanden for nogle View-elementer, såsom indholdet af EditText.
2.2 Gendan aktivitetsinstansens tilstand i onCreate()
Når du har gemt tilstanden Aktivitetsforekomst, skal du også gendanne den, når aktiviteten genskabes. Du kan gøre dette enten i onCreate() eller ved at implementere onRestoreInstanceState() callback, som kaldes efter onStart() efter at aktiviteten er oprettet.
Det meste af tiden er det bedre sted at gendanne aktivitetstilstanden i onCreate(), for at sikre, at brugergrænsefladen, inklusive tilstanden, er tilgængelig så hurtigt som muligt. Det er nogle gange praktisk at gøre det i onRestoreInstanceState() efter al initialiseringen er udført, eller at tillade underklasser at beslutte, om de skal bruge din standardimplementering.
- I onCreate()-metoden, efter at View-variablerne er initialiseret med findViewById(), skal du tilføje en test for at sikre, at savedInstanceState ikke er null.
// Initialize all the view variables.
mMessageEditText = findViewById(R.id.editText_main);
mReplyHeadTextView = findViewById(R.id.text_header_reply);
mReplyTextView = findViewById(R.id.text_message_reply);
// Restore the state.
if (savedInstanceState != null) {
}
Når din aktivitet er oprettet, sender systemet tilstandspakken til onCreate() som dets eneste argument. Første gang onCreate() kaldes, og din app starter, er pakken null – der er ingen eksisterende tilstand, første gang din app starter. Efterfølgende kald til onCreate() har en bundt udfyldt med de data, du har gemt i onSaveInstanceState().
- Inden i det tjek skal du få den aktuelle synlighed (sand eller falsk) ud af pakken med nøglen "reply_visible".
if (savedInstanceState != null) {
boolean isVisible =
savedInstanceState.getBoolean("reply_visible");
}
- Tilføj en test under den forrige linje for variabelen isVisible.
if (isVisible) {
}
Hvis der er en reply_visible-nøgle i tilstandspakken (og isVisible derfor er sand), skal du gendanne tilstanden.
- Gør overskriften synlig inde i isVisible-testen.
mReplyHeadTextView.setVisibility(View.VISIBLE);
- Hent tekstsvarbeskeden fra pakken med nøglen "reply_text", og indstil svaret TextView til at vise den streng.
mReplyTextView.setText(savedInstanceState.getString("reply_text"));
- Gør svaret TextView også synligt:
mReplyTextView.setVisibility(View.VISIBLE);
- Kør appen. Prøv at rotere enheden eller emulatoren for at sikre, at svarmeddelelsen (hvis der er en) forbliver på skærmen, efter at aktiviteten er genskabt.
Opgave 2 løsningskode
Følgende kodestykker viser løsningskoden for denne opgave.
Hovedaktivitet
Følgende kodestykker viser den tilføjede kode i MainActivity, men ikke hele klassen.
OnSaveInstanceState() metoden:
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
// If the heading is visible, message needs to be saved.
// Otherwise we're still using default layout.
if (mReplyHeadTextView.getVisibility() == View.VISIBLE) {
outState.putBoolean("reply_visible", true);
outState.putString("reply_text",
mReplyTextView.getText().toString());
}
}
OnCreate() metoden:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d(LOG_TAG, "-------");
Log.d(LOG_TAG, "onCreate");
// Initialize all the view variables.
mMessageEditText = findViewById(R.id.editText_main);
mReplyHeadTextView = findViewById(R.id.text_header_reply);
mReplyTextView = findViewById(R.id.text_message_reply);
// Restore the saved state.
// See onSaveInstanceState() for what gets saved.
if (savedInstanceState != null) {
boolean isVisible =
savedInstanceState.getBoolean("reply_visible");
// Show both the header and the message views. If isVisible is
// false or missing from the bundle, use the default layout.
if (isVisible) {
mReplyHeadTextView.setVisibility(View.VISIBLE);
mReplyTextView.setText(savedInstanceState
.getString("reply_text"));
mReplyTextView.setVisibility(View.VISIBLE);
}
}
}
Det komplette projekt:
Android Studio Project: TwoActivitiesLifecycle
5. Kodning
Udfordring: Opret en simpel indkøbsliste-app med en hovedaktivitet for den liste, brugeren er ved at opbygge, og en anden aktivitet for en liste over almindelige indkøbsvarer.
- Hovedaktiviteten skal indeholde listen, der skal bygges, som skal bestå af ti tomme TextView-elementer.
- En Tilføj vare-knap på hovedaktiviteten starter en anden aktivitet, der indeholder en liste over almindelige indkøbsvarer (ost, ris, æbler og så videre). Brug knapelementer til at vise elementerne.
- Valg af et element returnerer brugeren til hovedaktiviteten og opdaterer en tom TextView for at inkludere det valgte element.
Brug en hensigt til at videregive oplysninger fra en aktivitet til en anden. Sørg for, at den aktuelle tilstand af indkøbslisten er gemt, når brugeren roterer enheden.
6. Resumé
- Aktivitetslivscyklussen er et sæt tilstande, som en aktivitet migrerer igennem, begyndende når den først oprettes og slutter når Android-systemet genvinder ressourcerne til den pågældende aktivitet.
- Når brugeren navigerer fra én aktivitet til en anden, og i og uden for din app, flytter hver aktivitet mellem tilstande i aktivitetens livscyklus.
- Hver tilstand i aktivitetens livscyklus har en tilsvarende tilbagekaldsmetode, som du kan tilsidesætte i din aktivitetsklasse.
- Livscyklusmetoderne er onCreate(), onStart(), onPause(), onRestart(), onResume(), onStop(), onDestroy().
- Tilsidesættelse af en livscyklus-tilbagekaldsmetode giver dig mulighed for at tilføje adfærd, der opstår, når din aktivitet overgår til denne tilstand.
- Du kan tilføje skelettilsidesættelsesmetoder til dine klasser i Android Studio med Kode > Tilsidesæt.
- Ændringer i enhedskonfigurationen, såsom rotation, resulterer i, at aktiviteten bliver ødelagt og genskabt, som om den var ny.
- En del af aktivitetstilstanden bevares ved en konfigurationsændring, inklusive de aktuelle værdier af EditText-elementer. For alle andre data skal du udtrykkeligt selv gemme disse data.
- Gem aktivitetsforekomsttilstand i onSaveInstanceState()-metoden.
- Forekomsttilstandsdata gemmes som simple nøgle/værdipar i en bundle. Brug pakkemetoderne til at lægge data ind i og få data tilbage fra pakken.
- Gendan instanstilstanden i onCreate(), som er den foretrukne måde, eller onRestoreInstanceState(). Tilbage
1. Velkommen
Dette praktiske codelab er en del af Unit 1: Kom godt i gang med Android Developer Fundamentals (Version 2)-kurset. Du vil få mest muligt ud af dette kursus, hvis du arbejder gennem codelabs i rækkefølge:
- For den komplette liste over codelabs i kurset, se Codelabs for Android Developer Fundamentals (V2).
- For detaljer om kurset, inklusive links til alle konceptkapitlerne, apps og slides, se Android Developer Fundamentals (version 2).
Indledning
I denne praktik lærer du mere om aktivitetens livscyklus. Livscyklussen er det sæt af tilstande, en aktivitet kan befinde sig i i hele sin levetid, fra den er oprettet, til den bliver ødelagt, og systemet genvinder sine ressourcer. Når en bruger navigerer mellem aktiviteter i din app (såvel som ind og ud af din app), skifter aktiviteter mellem forskellige tilstande i deres livscyklus.
Hvert trin i en aktivitets livscyklus har en tilsvarende tilbagekaldsmetode: onCreate(), onStart(), onPause() og så videre. Når en aktivitet ændrer tilstand, aktiveres den tilknyttede tilbagekaldsmetode. Du har allerede set en af disse metoder: onCreate(). Ved at tilsidesætte en af livscyklus-tilbagekaldsmetoderne i dine aktivitetsklasser kan du ændre aktivitetens standardadfærd som svar på bruger- eller systemhandlinger.
Aktivitetstilstanden kan også ændre sig som reaktion på enhedskonfigurationsændringer, for eksempel når brugeren roterer enheden fra portræt til landskab. Når disse konfigurationsændringer sker, ødelægges aktiviteten og genskabes i sin standardtilstand, og brugeren kan miste oplysninger, som de har indtastet i aktiviteten. For at undgå at forvirre dine brugere, er det vigtigt, at du udvikler din app for at forhindre uventet datatab. Senere i denne praktik eksperimenterer du med konfigurationsændringer og lærer, hvordan du bevarer en aktivitets tilstand som reaktion på enhedskonfigurationsændringer og andre aktivitetslivscyklushændelser.
I denne praktiske øvelse tilføjer du logningserklæringer til TwoActivities-appen og observerer ændringer i aktivitetens livscyklus, mens du bruger appen. Du begynder derefter at arbejde med disse ændringer og undersøge, hvordan du håndterer brugerinput under disse forhold.
Forudsætninger
Du skal kunne:
- Opret og kør et app-projekt i Android Studio .
- Tilføj logerklæringer til din app, og se disse logfiler i Logcat-ruden.
- Forstå og arbejde med en aktivitet og en hensigt, og vær komfortabel med at interagere med dem.
Hvad du vil lære
- Sådan fungerer aktivitetens livscyklus.
- Når en aktivitet starter, pauser, stopper og ødelægges.
- Om de livscyklus-tilbagekaldsmetoder, der er forbundet med aktivitetsændringer.
- Effekten af handlinger (såsom konfigurationsændringer), der kan resultere i aktivitetslivscyklushændelser.
- Sådan bevarer du aktivitetstilstand på tværs af livscyklushændelser.
Hvad du vil gøre
- Tilføj kode til TwoActivities -appen fra den forrige praktiske for at implementere de forskellige aktivitets-livscyklus-tilbagekald for at inkludere logningserklæringer.
- Observer tilstandsændringerne, mens din app kører, og når du interagerer med hver aktivitet i din app.
- Rediger din app for at bevare forekomsttilstanden for en aktivitet, der uventet genskabes som reaktion på brugeradfærd eller konfigurationsændringer på enheden.
2. App oversigt
I denne praktiske tilføjelse tilføjer du TwoActivities -appen. Appen ser ud og opfører sig nogenlunde det samme, som den gjorde i det sidste codelab. Den indeholder to Activity-implementeringer og giver brugeren mulighed for at sende mellem dem. De ændringer, du foretager i appen i denne praktiske, vil ikke påvirke dens synlige brugeradfærd.
3. 3. Opgave 1: Tilføj livscyklustilbagekald til TwoActivities
I denne opgave vil du implementere alle Aktivitets livscyklus-tilbagekaldsmetoder for at udskrive meddelelser til logcat, når disse metoder påkaldes. Disse logmeddelelser giver dig mulighed for at se, hvornår aktivitetens livscyklus ændrer tilstand, og hvordan disse ændringer i livscyklustilstanden påvirker din app, mens den kører.
1.1 (Valgfrit) Kopier TwoActivities-projektet
Til opgaverne i denne praktik, vil du ændre det eksisterende TwoActivities -projekt, du byggede i den sidste praktik. Hvis du foretrækker at beholde det tidligere TwoActivities-projekt intakt, skal du følge trinene i Appendiks: Hjælpeprogrammer for at lave en kopi af projektet.
1.2 Implementer tilbagekald i MainActivity
- Åbn TwoActivities-projektet i Android Studio, og åbn MainActivity i panelet Projekt > Android.
- Tilføj følgende logsætninger i onCreate()-metoden:
Log.d(LOG_TAG, "-------");
Log.d(LOG_TAG, "onCreate");
- Tilføj en tilsidesættelse for onStart()-tilbagekaldet med en erklæring til loggen for den pågældende hændelse:
@Override
public void onStart(){
super.onStart();
Log.d(LOG_TAG, "onStart");
}
For en genvej skal du vælge Kode > Tilsidesæt metoder i Android Studio. Der vises en dialogboks med alle de mulige metoder, du kan tilsidesætte i din klasse. Hvis du vælger en eller flere tilbagekaldsmetoder fra listen, indsættes en komplet skabelon for disse metoder, inklusive det nødvendige kald til superklassen.
- Brug metoden onStart() som en skabelon til at implementere onPause(), onRestart(), onResume(), onStop() og onDestroy() livscyklus-tilbagekaldene
Alle tilbagekaldsmetoder har de samme signaturer (bortset fra navnet). Hvis du kopierer og indsætter onStart() for at oprette disse andre tilbagekaldsmetoder, så glem ikke at opdatere indholdet for at kalde den rigtige metode i superklassen og for at logge den korrekte metode.
- Kør din app.
- Klik på fanen Logcat i bunden af Android Studio for at vise Logcat-ruden. Du bør se tre log-meddelelser, der viser de tre livscyklustilstande, som aktiviteten er gået igennem, da den startede:
D/MainActivity: -------
D/MainActivity: onCreate
D/MainActivity: onStart
D/MainActivity: onResume
1.3 Implementer lifecycle callbacks i SecondActivity
Nu hvor du har implementeret livscyklus-tilbagekaldsmetoderne for MainActivity, skal du gøre det samme for SecondActivity.
- Åbn SecondActivity.
- Øverst i klassen skal du tilføje en konstant for variablen LOG_TAG:
private static final String LOG_TAG = SecondActivity.class.getSimpleName();
- Tilføj livscyklustilbagekaldene og logerklæringer til den anden aktivitet. (Du kan kopiere og indsætte tilbagekaldsmetoderne fra MainActivity.)
- Tilføj en logsætning til returnReply()-metoden lige før finish()-metoden:
Log.d(LOG_TAG, "End SecondActivity");
1.4 Observer loggen, mens appen kører**
- Kør din app.
- Klik på fanen Logcat i bunden af Android Studio for at vise Logcat-ruden.
- Indtast aktivitet i søgefeltet. Android logcat kan være meget lang og rodet. Fordi LOG_TAG-variablen i hver klasse indeholder enten ordene MainActivity eller SecondActivity, lader dette søgeord dig filtrere loggen for kun de ting, du er interesseret i.
Eksperimenter med din app, og bemærk, at de livscyklushændelser, der opstår som reaktion på forskellige handlinger. Prøv især disse ting:
- Brug appen normalt (send en besked, svar med en anden besked).
- Brug knappen Tilbage for at gå tilbage fra den anden aktivitet til hovedaktiviteten.
- Brug pil op på applinjen for at gå tilbage fra den anden aktivitet til hovedaktiviteten.
- Roter enheden på både hoved- og andenaktiviteten på forskellige tidspunkter i din app, og observer, hvad der sker i *-loggen og på skærmen.
- Tryk på oversigtsknappen (den firkantede knap til højre for Hjem), og luk appen (tryk på X).
- Vend tilbage til startskærmen og genstart din app.
TIP: Hvis du kører din app i en emulator, kan du simulere rotation med Control+F11 eller Control+Function+F11.
Opgave 1 løsningskode
Følgende kodestykker viser løsningskoden for den første opgave.
Hovedaktivitet
Følgende kodestykker viser den tilføjede kode i MainActivity, men ikke hele klassen.
OnCreate() metoden:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Log the start of the onCreate() method.
Log.d(LOG_TAG, "-------");
Log.d(LOG_TAG, "onCreate");
// Initialize all the view variables.
mMessageEditText = findViewById(R.id.editText_main);
mReplyHeadTextView = findViewById(R.id.text_header_reply);
mReplyTextView = findViewById(R.id.text_message_reply);
}
De andre livscyklusmetoder:
@Override
protected void onStart() {
super.onStart();
Log.d(LOG_TAG, "onStart");
}
@Override
protected void onPause() {
super.onPause();
Log.d(LOG_TAG, "onPause");
}
@Override
protected void onRestart() {
super.onRestart();
Log.d(LOG_TAG, "onRestart");
}
@Override
protected void onResume() {
super.onResume();
Log.d(LOG_TAG, "onResume");
}
@Override
protected void onStop() {
super.onStop();
Log.d(LOG_TAG, "onStop");
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.d(LOG_TAG, "onDestroy");
}
SecondActivity
Følgende kodestykker viser den tilføjede kode i SecondActivity, men ikke hele klassen.
Øverst i SecondActivity-klassen:
private static final String LOG_TAG = SecondActivity.class.getSimpleName();
ReturnReply() metoden:
public void returnReply(View view) {
String reply = mReply.getText().toString();
Intent replyIntent = new Intent();
replyIntent.putExtra(EXTRA_REPLY, reply);
setResult(RESULT_OK, replyIntent);
Log.d(LOG_TAG, "End SecondActivity");
finish();
}
De andre livscyklusmetoder:
Samme som for MainActivity ovenfor.
4. 4. Opgave 2: Gem og gendan tilstanden Aktivitetsforekomst
Afhængigt af systemressourcer og brugeradfærd kan hver aktivitet i din app blive ødelagt og rekonstrueret langt oftere, end du måske tror.
Du har muligvis bemærket denne adfærd i det sidste afsnit, da du roterede enheden eller emulatoren. Rotation af enheden er et eksempel på en enhedskonfigurationsændring. Selvom rotation er den mest almindelige, resulterer alle konfigurationsændringer i, at den aktuelle aktivitet bliver ødelagt og genskabt, som om den var ny. Hvis du ikke tager højde for denne adfærd i din kode, når der sker en konfigurationsændring, kan dit aktivitetslayout vende tilbage til dets standardudseende og startværdier, og dine brugere kan miste deres plads, deres data eller status for deres fremskridt i din app.
Tilstanden for hver aktivitet er gemt som et sæt nøgle/værdi-par i et bundleobjekt kaldet aktivitetsinstanstilstanden. Systemet gemmer standardtilstandsoplysninger til instanstilstandsbundt lige før aktiviteten stoppes, og sender denne bundt til den nye aktivitetsforekomst for at gendanne.
For at undgå at miste data i en aktivitet, når de uventet bliver ødelagt og genskabt, skal du implementere onSaveInstanceState()-metoden. Systemet kalder denne metode på din aktivitet (mellem onPause() og onStop()), når der er mulighed for, at aktiviteten kan blive ødelagt og genskabt.
De data, du gemmer i instanstilstanden, er kun specifikke for denne instans af denne specifikke aktivitet under den aktuelle appsession. Når du stopper og genstarter en ny app-session, går tilstanden Aktivitetsforekomst tabt, og aktiviteten vender tilbage til sit standardudseende. Hvis du har brug for at gemme brugerdata mellem app-sessioner, skal du bruge delte præferencer eller en database. Du lærer om begge disse i en senere praktik.
2.1 Gem aktivitetsforekomsttilstanden med onSaveInstanceState()
Du har måske bemærket, at rotation af enheden slet ikke påvirker tilstanden af den anden aktivitet. Dette skyldes, at det andet aktivitetslayout og -tilstand genereres ud fra layoutet og den hensigt, der aktiverede det. Selvom aktiviteten genskabes, er hensigten der stadig, og dataene i den hensigt bruges stadig, hver gang onCreate()-metoden i den anden aktivitet kaldes.
Derudover kan du bemærke, at i hver aktivitet bevares enhver tekst, du har indtastet i meddelelsen eller svar EditText-elementer, selv når enheden roteres. Dette skyldes, at tilstandsoplysningerne for nogle af View-elementerne i dit layout automatisk gemmes på tværs af konfigurationsændringer, og den aktuelle værdi af en EditText er et af disse tilfælde.
Så den eneste aktivitetstilstand, du er interesseret i, er TextView-elementerne for svaroverskriften og svarteksten i hovedaktiviteten. Begge TextView-elementer er usynlige som standard; de vises kun, når du sender en besked tilbage til hovedaktiviteten fra den anden aktivitet.
I denne opgave tilføjer du kode for at bevare instanstilstanden for disse to TextView-elementer ved hjælp af onSaveInstanceState().
- Åbn MainActivity.
- Føj denne skeletimplementering af onSaveInstanceState() til aktiviteten, eller brug Kode > Tilsidesættelsesmetoder til at indsætte en skelettilsidesættelse.
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
}
- Tjek for at se, om headeren i øjeblikket er synlig, og hvis det er tilfældet, indsæt den synlighedstilstand i tilstandspakken med putBoolean()-metoden og nøglen "reply_visible".
if (mReplyHeadTextView.getVisibility() == View.VISIBLE) {
outState.putBoolean("reply_visible", true);
}
Husk, at svaroverskriften og teksten er markeret som usynlige, indtil der er et svar fra den anden aktivitet. Hvis overskriften er synlig, så er der svardata, der skal gemmes. Bemærk, at vi kun er interesserede i denne synlighedstilstand - den faktiske tekst i overskriften behøver ikke at blive gemt, fordi den tekst aldrig ændres.
- Inden i den samme markering skal du tilføje svarteksten i pakken.
outState.putString("reply_text",mReplyTextView.getText().toString());
Hvis overskriften er synlig, kan du antage, at selve svarmeddelelsen også er synlig. Du behøver ikke at teste for eller gemme den aktuelle synlighedstilstand for svarbeskeden. Kun den faktiske tekst i beskeden går ind i tilstandspakken med nøglen "reply_text".
Du gemmer kun tilstanden for de View-elementer, der kan ændre sig, efter at aktiviteten er oprettet. De andre View-elementer i din app (Redigeringsteksten, knappen) kan til enhver tid genskabes fra standardlayoutet.
Bemærk, at systemet gemmer tilstanden for nogle View-elementer, såsom indholdet af EditText.
2.2 Gendan aktivitetsinstansens tilstand i onCreate()
Når du har gemt tilstanden Aktivitetsforekomst, skal du også gendanne den, når aktiviteten genskabes. Du kan gøre dette enten i onCreate() eller ved at implementere onRestoreInstanceState() callback, som kaldes efter onStart() efter at aktiviteten er oprettet.
Det meste af tiden er det bedre sted at gendanne aktivitetstilstanden i onCreate(), for at sikre, at brugergrænsefladen, inklusive tilstanden, er tilgængelig så hurtigt som muligt. Det er nogle gange praktisk at gøre det i onRestoreInstanceState() efter al initialiseringen er udført, eller at tillade underklasser at beslutte, om de skal bruge din standardimplementering.
- I onCreate()-metoden, efter at View-variablerne er initialiseret med findViewById(), skal du tilføje en test for at sikre, at savedInstanceState ikke er null.
// Initialize all the view variables.
mMessageEditText = findViewById(R.id.editText_main);
mReplyHeadTextView = findViewById(R.id.text_header_reply);
mReplyTextView = findViewById(R.id.text_message_reply);
// Restore the state.
if (savedInstanceState != null) {
}
Når din aktivitet er oprettet, sender systemet tilstandspakken til onCreate() som dets eneste argument. Første gang onCreate() kaldes, og din app starter, er pakken null – der er ingen eksisterende tilstand, første gang din app starter. Efterfølgende kald til onCreate() har en bundt udfyldt med de data, du har gemt i onSaveInstanceState().
- Inden i det tjek skal du få den aktuelle synlighed (sand eller falsk) ud af pakken med nøglen "reply_visible".
if (savedInstanceState != null) {
boolean isVisible =
savedInstanceState.getBoolean("reply_visible");
}
- Tilføj en test under den forrige linje for variabelen isVisible.
if (isVisible) {
}
Hvis der er en reply_visible-nøgle i tilstandspakken (og isVisible derfor er sand), skal du gendanne tilstanden.
- Gør overskriften synlig inde i isVisible-testen.
mReplyHeadTextView.setVisibility(View.VISIBLE);
- Hent tekstsvarbeskeden fra pakken med nøglen "reply_text", og indstil svaret TextView til at vise den streng.
mReplyTextView.setText(savedInstanceState.getString("reply_text"));
- Gør svaret TextView også synligt:
mReplyTextView.setVisibility(View.VISIBLE);
- Kør appen. Prøv at rotere enheden eller emulatoren for at sikre, at svarmeddelelsen (hvis der er en) forbliver på skærmen, efter at aktiviteten er genskabt.
Opgave 2 løsningskode
Følgende kodestykker viser løsningskoden for denne opgave.
Hovedaktivitet
Følgende kodestykker viser den tilføjede kode i MainActivity, men ikke hele klassen.
OnSaveInstanceState() metoden:
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
// If the heading is visible, message needs to be saved.
// Otherwise we're still using default layout.
if (mReplyHeadTextView.getVisibility() == View.VISIBLE) {
outState.putBoolean("reply_visible", true);
outState.putString("reply_text",
mReplyTextView.getText().toString());
}
}
OnCreate() metoden:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d(LOG_TAG, "-------");
Log.d(LOG_TAG, "onCreate");
// Initialize all the view variables.
mMessageEditText = findViewById(R.id.editText_main);
mReplyHeadTextView = findViewById(R.id.text_header_reply);
mReplyTextView = findViewById(R.id.text_message_reply);
// Restore the saved state.
// See onSaveInstanceState() for what gets saved.
if (savedInstanceState != null) {
boolean isVisible =
savedInstanceState.getBoolean("reply_visible");
// Show both the header and the message views. If isVisible is
// false or missing from the bundle, use the default layout.
if (isVisible) {
mReplyHeadTextView.setVisibility(View.VISIBLE);
mReplyTextView.setText(savedInstanceState
.getString("reply_text"));
mReplyTextView.setVisibility(View.VISIBLE);
}
}
}
Det komplette projekt:
Android Studio Project: TwoActivitiesLifecycle
5. Kodning
Udfordring: Opret en simpel indkøbsliste-app med en hovedaktivitet for den liste, brugeren er ved at opbygge, og en anden aktivitet for en liste over almindelige indkøbsvarer.
- Hovedaktiviteten skal indeholde listen, der skal bygges, som skal bestå af ti tomme TextView-elementer.
- En Tilføj vare-knap på hovedaktiviteten starter en anden aktivitet, der indeholder en liste over almindelige indkøbsvarer (ost, ris, æbler og så videre). Brug knapelementer til at vise elementerne.
- Valg af et element returnerer brugeren til hovedaktiviteten og opdaterer en tom TextView for at inkludere det valgte element.
Brug en hensigt til at videregive oplysninger fra en aktivitet til en anden. Sørg for, at den aktuelle tilstand af indkøbslisten er gemt, når brugeren roterer enheden.
6. Resumé
- Aktivitetslivscyklussen er et sæt tilstande, som en aktivitet migrerer igennem, begyndende når den først oprettes og slutter når Android-systemet genvinder ressourcerne til den pågældende aktivitet.
- Når brugeren navigerer fra én aktivitet til en anden, og i og uden for din app, flytter hver aktivitet mellem tilstande i aktivitetens livscyklus.
- Hver tilstand i aktivitetens livscyklus har en tilsvarende tilbagekaldsmetode, som du kan tilsidesætte i din aktivitetsklasse.
- Livscyklusmetoderne er onCreate(), onStart(), onPause(), onRestart(), onResume(), onStop(), onDestroy().
- Tilsidesættelse af en livscyklus-tilbagekaldsmetode giver dig mulighed for at tilføje adfærd, der opstår, når din aktivitet overgår til denne tilstand.
- Du kan tilføje skelettilsidesættelsesmetoder til dine klasser i Android Studio med Kode > Tilsidesæt.
- Ændringer i enhedskonfigurationen, såsom rotation, resulterer i, at aktiviteten bliver ødelagt og genskabt, som om den var ny.
- En del af aktivitetstilstanden bevares ved en konfigurationsændring, inklusive de aktuelle værdier af EditText-elementer. For alle andre data skal du udtrykkeligt selv gemme disse data.
- Gem aktivitetsforekomsttilstand i onSaveInstanceState()-metoden.
- Forekomsttilstandsdata gemmes som simple nøgle/værdipar i en bundle. Brug pakkemetoderne til at lægge data ind i og få data tilbage fra pakken.
- Gendan instanstilstanden i onCreate(), som er den foretrukne måde, eller onRestoreInstanceState(). Tilbage
1. Velkommen
Dette praktiske codelab er en del af Unit 1: Kom godt i gang med Android Developer Fundamentals (Version 2)-kurset. Du vil få mest muligt ud af dette kursus, hvis du arbejder gennem codelabs i rækkefølge:
- For den komplette liste over codelabs i kurset, se Codelabs for Android Developer Fundamentals (V2).
- For detaljer om kurset, inklusive links til alle konceptkapitlerne, apps og slides, se Android Developer Fundamentals (version 2).
Indledning
I denne praktik lærer du mere om aktivitetens livscyklus. Livscyklussen er det sæt af tilstande, en aktivitet kan befinde sig i i hele sin levetid, fra den er oprettet, til den bliver ødelagt, og systemet genvinder sine ressourcer. Når en bruger navigerer mellem aktiviteter i din app (såvel som ind og ud af din app), skifter aktiviteter mellem forskellige tilstande i deres livscyklus.
Hvert trin i en aktivitets livscyklus har en tilsvarende tilbagekaldsmetode: onCreate(), onStart(), onPause() og så videre. Når en aktivitet ændrer tilstand, aktiveres den tilknyttede tilbagekaldsmetode. Du har allerede set en af disse metoder: onCreate(). Ved at tilsidesætte en af livscyklus-tilbagekaldsmetoderne i dine aktivitetsklasser kan du ændre aktivitetens standardadfærd som svar på bruger- eller systemhandlinger.
Aktivitetstilstanden kan også ændre sig som reaktion på enhedskonfigurationsændringer, for eksempel når brugeren roterer enheden fra portræt til landskab. Når disse konfigurationsændringer sker, ødelægges aktiviteten og genskabes i sin standardtilstand, og brugeren kan miste oplysninger, som de har indtastet i aktiviteten. For at undgå at forvirre dine brugere, er det vigtigt, at du udvikler din app for at forhindre uventet datatab. Senere i denne praktik eksperimenterer du med konfigurationsændringer og lærer, hvordan du bevarer en aktivitets tilstand som reaktion på enhedskonfigurationsændringer og andre aktivitetslivscyklushændelser.
I denne praktiske øvelse tilføjer du logningserklæringer til TwoActivities-appen og observerer ændringer i aktivitetens livscyklus, mens du bruger appen. Du begynder derefter at arbejde med disse ændringer og undersøge, hvordan du håndterer brugerinput under disse forhold.
Forudsætninger
Du skal kunne:
- Opret og kør et app-projekt i Android Studio .
- Tilføj logerklæringer til din app, og se disse logfiler i Logcat-ruden.
- Forstå og arbejde med en aktivitet og en hensigt, og vær komfortabel med at interagere med dem.
Hvad du vil lære
- Sådan fungerer aktivitetens livscyklus.
- Når en aktivitet starter, pauser, stopper og ødelægges.
- Om de livscyklus-tilbagekaldsmetoder, der er forbundet med aktivitetsændringer.
- Effekten af handlinger (såsom konfigurationsændringer), der kan resultere i aktivitetslivscyklushændelser.
- Sådan bevarer du aktivitetstilstand på tværs af livscyklushændelser.
Hvad du vil gøre
- Tilføj kode til TwoActivities -appen fra den forrige praktiske for at implementere de forskellige aktivitets-livscyklus-tilbagekald for at inkludere logningserklæringer.
- Observer tilstandsændringerne, mens din app kører, og når du interagerer med hver aktivitet i din app.
- Rediger din app for at bevare forekomsttilstanden for en aktivitet, der uventet genskabes som reaktion på brugeradfærd eller konfigurationsændringer på enheden.
2. App oversigt
I denne praktiske tilføjelse tilføjer du TwoActivities -appen. Appen ser ud og opfører sig nogenlunde det samme, som den gjorde i det sidste codelab. Den indeholder to Activity-implementeringer og giver brugeren mulighed for at sende mellem dem. De ændringer, du foretager i appen i denne praktiske, vil ikke påvirke dens synlige brugeradfærd.
3. 3. Opgave 1: Tilføj livscyklustilbagekald til TwoActivities
I denne opgave vil du implementere alle Aktivitets livscyklus-tilbagekaldsmetoder for at udskrive meddelelser til logcat, når disse metoder påkaldes. Disse logmeddelelser giver dig mulighed for at se, hvornår aktivitetens livscyklus ændrer tilstand, og hvordan disse ændringer i livscyklustilstanden påvirker din app, mens den kører.
1.1 (Valgfrit) Kopier TwoActivities-projektet
Til opgaverne i denne praktik, vil du ændre det eksisterende TwoActivities -projekt, du byggede i den sidste praktik. Hvis du foretrækker at beholde det tidligere TwoActivities-projekt intakt, skal du følge trinene i Appendiks: Hjælpeprogrammer for at lave en kopi af projektet.
1.2 Implementer tilbagekald i MainActivity
- Åbn TwoActivities-projektet i Android Studio, og åbn MainActivity i panelet Projekt > Android.
- Tilføj følgende logsætninger i onCreate()-metoden:
Log.d(LOG_TAG, "-------");
Log.d(LOG_TAG, "onCreate");
- Tilføj en tilsidesættelse for onStart()-tilbagekaldet med en erklæring til loggen for den pågældende hændelse:
@Override
public void onStart(){
super.onStart();
Log.d(LOG_TAG, "onStart");
}
For en genvej skal du vælge Kode > Tilsidesæt metoder i Android Studio. Der vises en dialogboks med alle de mulige metoder, du kan tilsidesætte i din klasse. Hvis du vælger en eller flere tilbagekaldsmetoder fra listen, indsættes en komplet skabelon for disse metoder, inklusive det nødvendige kald til superklassen.
- Brug metoden onStart() som en skabelon til at implementere onPause(), onRestart(), onResume(), onStop() og onDestroy() livscyklus-tilbagekaldene
Alle tilbagekaldsmetoder har de samme signaturer (bortset fra navnet). Hvis du kopierer og indsætter onStart() for at oprette disse andre tilbagekaldsmetoder, så glem ikke at opdatere indholdet for at kalde den rigtige metode i superklassen og for at logge den korrekte metode.
- Kør din app.
- Klik på fanen Logcat i bunden af Android Studio for at vise Logcat-ruden. Du bør se tre log-meddelelser, der viser de tre livscyklustilstande, som aktiviteten er gået igennem, da den startede:
D/MainActivity: -------
D/MainActivity: onCreate
D/MainActivity: onStart
D/MainActivity: onResume
1.3 Implementer lifecycle callbacks i SecondActivity
Nu hvor du har implementeret livscyklus-tilbagekaldsmetoderne for MainActivity, skal du gøre det samme for SecondActivity.
- Åbn SecondActivity.
- Øverst i klassen skal du tilføje en konstant for variablen LOG_TAG:
private static final String LOG_TAG = SecondActivity.class.getSimpleName();
- Tilføj livscyklustilbagekaldene og logerklæringer til den anden aktivitet. (Du kan kopiere og indsætte tilbagekaldsmetoderne fra MainActivity.)
- Tilføj en logsætning til returnReply()-metoden lige før finish()-metoden:
Log.d(LOG_TAG, "End SecondActivity");
1.4 Observer loggen, mens appen kører**
- Kør din app.
- Klik på fanen Logcat i bunden af Android Studio for at vise Logcat-ruden.
- Indtast aktivitet i søgefeltet. Android logcat kan være meget lang og rodet. Fordi LOG_TAG-variablen i hver klasse indeholder enten ordene MainActivity eller SecondActivity, lader dette søgeord dig filtrere loggen for kun de ting, du er interesseret i.
Eksperimenter med din app, og bemærk, at de livscyklushændelser, der opstår som reaktion på forskellige handlinger. Prøv især disse ting:
- Brug appen normalt (send en besked, svar med en anden besked).
- Brug knappen Tilbage for at gå tilbage fra den anden aktivitet til hovedaktiviteten.
- Brug pil op på applinjen for at gå tilbage fra den anden aktivitet til hovedaktiviteten.
- Roter enheden på både hoved- og andenaktiviteten på forskellige tidspunkter i din app, og observer, hvad der sker i *-loggen og på skærmen.
- Tryk på oversigtsknappen (den firkantede knap til højre for Hjem), og luk appen (tryk på X).
- Vend tilbage til startskærmen og genstart din app.
TIP: Hvis du kører din app i en emulator, kan du simulere rotation med Control+F11 eller Control+Function+F11.
Opgave 1 løsningskode
Følgende kodestykker viser løsningskoden for den første opgave.
Hovedaktivitet
Følgende kodestykker viser den tilføjede kode i MainActivity, men ikke hele klassen.
OnCreate() metoden:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Log the start of the onCreate() method.
Log.d(LOG_TAG, "-------");
Log.d(LOG_TAG, "onCreate");
// Initialize all the view variables.
mMessageEditText = findViewById(R.id.editText_main);
mReplyHeadTextView = findViewById(R.id.text_header_reply);
mReplyTextView = findViewById(R.id.text_message_reply);
}
De andre livscyklusmetoder:
@Override
protected void onStart() {
super.onStart();
Log.d(LOG_TAG, "onStart");
}
@Override
protected void onPause() {
super.onPause();
Log.d(LOG_TAG, "onPause");
}
@Override
protected void onRestart() {
super.onRestart();
Log.d(LOG_TAG, "onRestart");
}
@Override
protected void onResume() {
super.onResume();
Log.d(LOG_TAG, "onResume");
}
@Override
protected void onStop() {
super.onStop();
Log.d(LOG_TAG, "onStop");
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.d(LOG_TAG, "onDestroy");
}
SecondActivity
Følgende kodestykker viser den tilføjede kode i SecondActivity, men ikke hele klassen.
Øverst i SecondActivity-klassen:
private static final String LOG_TAG = SecondActivity.class.getSimpleName();
ReturnReply() metoden:
public void returnReply(View view) {
String reply = mReply.getText().toString();
Intent replyIntent = new Intent();
replyIntent.putExtra(EXTRA_REPLY, reply);
setResult(RESULT_OK, replyIntent);
Log.d(LOG_TAG, "End SecondActivity");
finish();
}
De andre livscyklusmetoder:
Samme som for MainActivity ovenfor.
4. 4. Opgave 2: Gem og gendan tilstanden Aktivitetsforekomst
Afhængigt af systemressourcer og brugeradfærd kan hver aktivitet i din app blive ødelagt og rekonstrueret langt oftere, end du måske tror.
Du har muligvis bemærket denne adfærd i det sidste afsnit, da du roterede enheden eller emulatoren. Rotation af enheden er et eksempel på en enhedskonfigurationsændring. Selvom rotation er den mest almindelige, resulterer alle konfigurationsændringer i, at den aktuelle aktivitet bliver ødelagt og genskabt, som om den var ny. Hvis du ikke tager højde for denne adfærd i din kode, når der sker en konfigurationsændring, kan dit aktivitetslayout vende tilbage til dets standardudseende og startværdier, og dine brugere kan miste deres plads, deres data eller status for deres fremskridt i din app.
Tilstanden for hver aktivitet er gemt som et sæt nøgle/værdi-par i et bundleobjekt kaldet aktivitetsinstanstilstanden. Systemet gemmer standardtilstandsoplysninger til instanstilstandsbundt lige før aktiviteten stoppes, og sender denne bundt til den nye aktivitetsforekomst for at gendanne.
For at undgå at miste data i en aktivitet, når de uventet bliver ødelagt og genskabt, skal du implementere onSaveInstanceState()-metoden. Systemet kalder denne metode på din aktivitet (mellem onPause() og onStop()), når der er mulighed for, at aktiviteten kan blive ødelagt og genskabt.
De data, du gemmer i instanstilstanden, er kun specifikke for denne instans af denne specifikke aktivitet under den aktuelle appsession. Når du stopper og genstarter en ny app-session, går tilstanden Aktivitetsforekomst tabt, og aktiviteten vender tilbage til sit standardudseende. Hvis du har brug for at gemme brugerdata mellem app-sessioner, skal du bruge delte præferencer eller en database. Du lærer om begge disse i en senere praktik.
2.1 Gem aktivitetsforekomsttilstanden med onSaveInstanceState()
Du har måske bemærket, at rotation af enheden slet ikke påvirker tilstanden af den anden aktivitet. Dette skyldes, at det andet aktivitetslayout og -tilstand genereres ud fra layoutet og den hensigt, der aktiverede det. Selvom aktiviteten genskabes, er hensigten der stadig, og dataene i den hensigt bruges stadig, hver gang onCreate()-metoden i den anden aktivitet kaldes.
Derudover kan du bemærke, at i hver aktivitet bevares enhver tekst, du har indtastet i meddelelsen eller svar EditText-elementer, selv når enheden roteres. Dette skyldes, at tilstandsoplysningerne for nogle af View-elementerne i dit layout automatisk gemmes på tværs af konfigurationsændringer, og den aktuelle værdi af en EditText er et af disse tilfælde.
Så den eneste aktivitetstilstand, du er interesseret i, er TextView-elementerne for svaroverskriften og svarteksten i hovedaktiviteten. Begge TextView-elementer er usynlige som standard; de vises kun, når du sender en besked tilbage til hovedaktiviteten fra den anden aktivitet.
I denne opgave tilføjer du kode for at bevare instanstilstanden for disse to TextView-elementer ved hjælp af onSaveInstanceState().
- Åbn MainActivity.
- Føj denne skeletimplementering af onSaveInstanceState() til aktiviteten, eller brug Kode > Tilsidesættelsesmetoder til at indsætte en skelettilsidesættelse.
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
}
- Tjek for at se, om headeren i øjeblikket er synlig, og hvis det er tilfældet, indsæt den synlighedstilstand i tilstandspakken med putBoolean()-metoden og nøglen "reply_visible".
if (mReplyHeadTextView.getVisibility() == View.VISIBLE) {
outState.putBoolean("reply_visible", true);
}
Husk, at svaroverskriften og teksten er markeret som usynlige, indtil der er et svar fra den anden aktivitet. Hvis overskriften er synlig, så er der svardata, der skal gemmes. Bemærk, at vi kun er interesserede i denne synlighedstilstand - den faktiske tekst i overskriften behøver ikke at blive gemt, fordi den tekst aldrig ændres.
- Inden i den samme markering skal du tilføje svarteksten i pakken.
outState.putString("reply_text",mReplyTextView.getText().toString());
Hvis overskriften er synlig, kan du antage, at selve svarmeddelelsen også er synlig. Du behøver ikke at teste for eller gemme den aktuelle synlighedstilstand for svarbeskeden. Kun den faktiske tekst i beskeden går ind i tilstandspakken med nøglen "reply_text".
Du gemmer kun tilstanden for de View-elementer, der kan ændre sig, efter at aktiviteten er oprettet. De andre View-elementer i din app (Redigeringsteksten, knappen) kan til enhver tid genskabes fra standardlayoutet.
Bemærk, at systemet gemmer tilstanden for nogle View-elementer, såsom indholdet af EditText.
2.2 Gendan aktivitetsinstansens tilstand i onCreate()
Når du har gemt tilstanden Aktivitetsforekomst, skal du også gendanne den, når aktiviteten genskabes. Du kan gøre dette enten i onCreate() eller ved at implementere onRestoreInstanceState() callback, som kaldes efter onStart() efter at aktiviteten er oprettet.
Det meste af tiden er det bedre sted at gendanne aktivitetstilstanden i onCreate(), for at sikre, at brugergrænsefladen, inklusive tilstanden, er tilgængelig så hurtigt som muligt. Det er nogle gange praktisk at gøre det i onRestoreInstanceState() efter al initialiseringen er udført, eller at tillade underklasser at beslutte, om de skal bruge din standardimplementering.
- I onCreate()-metoden, efter at View-variablerne er initialiseret med findViewById(), skal du tilføje en test for at sikre, at savedInstanceState ikke er null.
// Initialize all the view variables.
mMessageEditText = findViewById(R.id.editText_main);
mReplyHeadTextView = findViewById(R.id.text_header_reply);
mReplyTextView = findViewById(R.id.text_message_reply);
// Restore the state.
if (savedInstanceState != null) {
}
Når din aktivitet er oprettet, sender systemet tilstandspakken til onCreate() som dets eneste argument. Første gang onCreate() kaldes, og din app starter, er pakken null – der er ingen eksisterende tilstand, første gang din app starter. Efterfølgende kald til onCreate() har en bundt udfyldt med de data, du har gemt i onSaveInstanceState().
- Inden i det tjek skal du få den aktuelle synlighed (sand eller falsk) ud af pakken med nøglen "reply_visible".
if (savedInstanceState != null) {
boolean isVisible =
savedInstanceState.getBoolean("reply_visible");
}
- Tilføj en test under den forrige linje for variabelen isVisible.
if (isVisible) {
}
Hvis der er en reply_visible-nøgle i tilstandspakken (og isVisible derfor er sand), skal du gendanne tilstanden.
- Gør overskriften synlig inde i isVisible-testen.
mReplyHeadTextView.setVisibility(View.VISIBLE);
- Hent tekstsvarbeskeden fra pakken med nøglen "reply_text", og indstil svaret TextView til at vise den streng.
mReplyTextView.setText(savedInstanceState.getString("reply_text"));
- Gør svaret TextView også synligt:
mReplyTextView.setVisibility(View.VISIBLE);
- Kør appen. Prøv at rotere enheden eller emulatoren for at sikre, at svarmeddelelsen (hvis der er en) forbliver på skærmen, efter at aktiviteten er genskabt.
Opgave 2 løsningskode
Følgende kodestykker viser løsningskoden for denne opgave.
Hovedaktivitet
Følgende kodestykker viser den tilføjede kode i MainActivity, men ikke hele klassen.
OnSaveInstanceState() metoden:
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
// If the heading is visible, message needs to be saved.
// Otherwise we're still using default layout.
if (mReplyHeadTextView.getVisibility() == View.VISIBLE) {
outState.putBoolean("reply_visible", true);
outState.putString("reply_text",
mReplyTextView.getText().toString());
}
}
OnCreate() metoden:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d(LOG_TAG, "-------");
Log.d(LOG_TAG, "onCreate");
// Initialize all the view variables.
mMessageEditText = findViewById(R.id.editText_main);
mReplyHeadTextView = findViewById(R.id.text_header_reply);
mReplyTextView = findViewById(R.id.text_message_reply);
// Restore the saved state.
// See onSaveInstanceState() for what gets saved.
if (savedInstanceState != null) {
boolean isVisible =
savedInstanceState.getBoolean("reply_visible");
// Show both the header and the message views. If isVisible is
// false or missing from the bundle, use the default layout.
if (isVisible) {
mReplyHeadTextView.setVisibility(View.VISIBLE);
mReplyTextView.setText(savedInstanceState
.getString("reply_text"));
mReplyTextView.setVisibility(View.VISIBLE);
}
}
}
Det komplette projekt:
Android Studio Project: TwoActivitiesLifecycle
5. Kodning
Udfordring: Opret en simpel indkøbsliste-app med en hovedaktivitet for den liste, brugeren er ved at opbygge, og en anden aktivitet for en liste over almindelige indkøbsvarer.
- Hovedaktiviteten skal indeholde listen, der skal bygges, som skal bestå af ti tomme TextView-elementer.
- En Tilføj vare-knap på hovedaktiviteten starter en anden aktivitet, der indeholder en liste over almindelige indkøbsvarer (ost, ris, æbler og så videre). Brug knapelementer til at vise elementerne.
- Valg af et element returnerer brugeren til hovedaktiviteten og opdaterer en tom TextView for at inkludere det valgte element.
Brug en hensigt til at videregive oplysninger fra en aktivitet til en anden. Sørg for, at den aktuelle tilstand af indkøbslisten er gemt, når brugeren roterer enheden.
6. Resumé
- Aktivitetslivscyklussen er et sæt tilstande, som en aktivitet migrerer igennem, begyndende når den først oprettes og slutter når Android-systemet genvinder ressourcerne til den pågældende aktivitet.
- Når brugeren navigerer fra én aktivitet til en anden, og i og uden for din app, flytter hver aktivitet mellem tilstande i aktivitetens livscyklus.
- Hver tilstand i aktivitetens livscyklus har en tilsvarende tilbagekaldsmetode, som du kan tilsidesætte i din aktivitetsklasse.
- Livscyklusmetoderne er onCreate(), onStart(), onPause(), onRestart(), onResume(), onStop(), onDestroy().
- Tilsidesættelse af en livscyklus-tilbagekaldsmetode giver dig mulighed for at tilføje adfærd, der opstår, når din aktivitet overgår til denne tilstand.
- Du kan tilføje skelettilsidesættelsesmetoder til dine klasser i Android Studio med Kode > Tilsidesæt.
- Ændringer i enhedskonfigurationen, såsom rotation, resulterer i, at aktiviteten bliver ødelagt og genskabt, som om den var ny.
- En del af aktivitetstilstanden bevares ved en konfigurationsændring, inklusive de aktuelle værdier af EditText-elementer. For alle andre data skal du udtrykkeligt selv gemme disse data.
- Gem aktivitetsforekomsttilstand i onSaveInstanceState()-metoden.
- Forekomsttilstandsdata gemmes som simple nøgle/værdipar i en bundle. Brug pakkemetoderne til at lægge data ind i og få data tilbage fra pakken.
- Gendan instanstilstanden i onCreate(), som er den foretrukne måde, eller onRestoreInstanceState(). Tilbage