1. Welkom
Dit praktische codelab maakt deel uit van Unit 1: Aan de slag met de cursus Android Developer Fundamentals (Versie 2). U haalt de meeste waarde uit deze cursus als u de codelabs op volgorde doorwerkt:
- Zie Codelabs for Android Developer Fundamentals (V2) voor de volledige lijst met codelabs in de cursus.
- Zie Android Developer Fundamentals (versie 2) voor meer informatie over de cursus, inclusief links naar alle concepthoofdstukken, apps en dia's.
Invoering
In dit practicum leer je meer over de levenscyclus van een activiteit. De levenscyclus is de reeks toestanden waarin een activiteit zich gedurende zijn gehele levensduur kan bevinden, vanaf het moment waarop deze wordt gemaakt tot het moment waarop deze wordt vernietigd en het systeem zijn hulpbronnen terugwint. Terwijl een gebruiker tussen activiteiten in uw app navigeert (en ook uw app in- en uitgaat), wisselen activiteiten tussen verschillende fasen in hun levenscyclus.
Elke fase in de levenscyclus van een activiteit heeft een bijbehorende callback-methode: onCreate(), onStart(), onPause(), enzovoort. Wanneer een activiteit van status verandert, wordt de bijbehorende callback-methode aangeroepen. Je hebt een van deze methoden al gezien: onCreate(). Door een van de levenscyclus-callback-methoden in uw activiteitsklassen te overschrijven, kunt u het standaardgedrag van de activiteit wijzigen als reactie op gebruikers- of systeemacties.
De activiteitsstatus kan ook veranderen als reactie op wijzigingen in de apparaatconfiguratie, bijvoorbeeld wanneer de gebruiker het apparaat van staand naar liggend draait. Wanneer deze configuratiewijzigingen plaatsvinden, wordt de activiteit vernietigd en opnieuw gemaakt in de standaardstatus, en kan de gebruiker de informatie kwijtraken die hij of zij in de activiteit heeft ingevoerd. Om verwarring bij uw gebruikers te voorkomen, is het belangrijk dat u uw app ontwikkelt om onverwacht gegevensverlies te voorkomen. Later in dit practicum experimenteer je met configuratiewijzigingen en leer je hoe je de status van een activiteit kunt behouden als reactie op wijzigingen in de apparaatconfiguratie en andere gebeurtenissen in de levenscyclus van een activiteit.
In dit practicum voegt u logboekverklaringen toe aan de TwoActivities-app en observeert u veranderingen in de levenscyclus van activiteiten terwijl u de app gebruikt. Vervolgens gaat u met deze wijzigingen aan de slag en onderzoekt u hoe u onder deze omstandigheden met gebruikersinvoer kunt omgaan.
Vereisten
Je zou in staat moeten zijn om:
- Maak en voer een app-project uit in Android Studio .
- Voeg logboekinstructies toe aan uw app en bekijk deze logboeken in het Logcat-venster.
- Begrijp en werk ermee met een activiteit en een intentie, en voel u op uw gemak bij de interactie ermee.
Wat je zult leren
- Hoe de activiteitslevenscyclus werkt.
- Wanneer een activiteit start, pauzeert, stopt en wordt vernietigd.
- Over de callback-methoden voor de levenscyclus die zijn gekoppeld aan activiteitswijzigingen.
- Het effect van acties (zoals configuratiewijzigingen) die kunnen resulteren in levenscyclusgebeurtenissen van activiteiten.
- Hoe u de activiteitsstatus kunt behouden tijdens levenscyclusgebeurtenissen.
Wat je gaat doen
- Voeg code uit het vorige practicum toe aan de TwoActivities -app om de verschillende callbacks voor de levenscyclus van activiteiten te implementeren en logboekinstructies op te nemen.
- Observeer de statusveranderingen terwijl uw app wordt uitgevoerd en terwijl u met elke activiteit in uw app communiceert.
- Pas uw app aan om de exemplaarstatus te behouden van een activiteit die onverwacht opnieuw wordt gemaakt als reactie op gebruikersgedrag of configuratiewijzigingen op het apparaat.
2. App-overzicht
In dit practicum voeg je iets toe aan de TwoActivities app. De app ziet er ongeveer hetzelfde uit en gedraagt zich ongeveer hetzelfde als in het laatste codelab. Het bevat twee activiteitsimplementaties en geeft de gebruiker de mogelijkheid om tussen deze te verzenden. De wijzigingen die u in dit practicum in de app aanbrengt, hebben geen invloed op het zichtbare gebruikersgedrag.
3. 3. Taak 1: levenscyclus-callbacks toevoegen aan TwoActivities
In deze taak implementeert u alle callback-methoden voor de activiteitslevenscyclus om berichten naar logcat af te drukken wanneer deze methoden worden aangeroepen. Met deze logboekberichten kunt u zien wanneer de levenscyclus van de activiteit van status verandert, en hoe deze wijzigingen in de levenscyclus van invloed zijn op uw app terwijl deze wordt uitgevoerd.
1.1 (Optioneel) Kopieer het TwoActivities-project
Voor de taken in dit practicum pas je het bestaande TwoActivities -project aan dat je in het laatste practicum hebt gebouwd. Als u het vorige TwoActivities-project liever intact wilt houden, volgt u de stappen in Bijlage: Hulpprogramma's om een kopie van het project te maken.
1.2 Implementeer callbacks in MainActivity
- Open het TwoActivities-project in Android Studio en open MainActivity in het paneel Project > Android.
- Voeg in de methode onCreate() de volgende loginstructies toe:
Log.d(LOG_TAG, "-------");
Log.d(LOG_TAG, "onCreate");
- Voeg een overschrijving toe voor de onStart() callback, met een verklaring voor het logboek voor die gebeurtenis:
@Override
public void onStart(){
super.onStart();
Log.d(LOG_TAG, "onStart");
}
Voor een snelkoppeling selecteert u Code > Methoden negeren in Android Studio. Er verschijnt een dialoogvenster met alle mogelijke methoden die u in uw klas kunt overschrijven. Als u een of meer callback-methoden uit de lijst kiest, wordt een volledige sjabloon voor die methoden ingevoegd, inclusief de vereiste aanroep naar de superklasse.
- Gebruik de methode onStart() als sjabloon om de levenscycluscallbacks onPause(), onRestart(), onResume(), onStop() en onDestroy() te implementeren
Alle callback-methoden hebben dezelfde handtekeningen (behalve de naam). Als u onStart() kopieert en plakt om deze andere callback-methoden te maken, vergeet dan niet de inhoud bij te werken om de juiste methode in de superklasse aan te roepen, en om de juiste methode te loggen.
- Voer uw app uit.
- Klik op het tabblad Logcat onder aan Android Studio om het Logcat-venster weer te geven. U zou drie logberichten moeten zien die de drie levenscyclusstatussen weergeven waar de activiteit doorheen is gegaan toen deze begon:
D/MainActivity: -------
D/MainActivity: onCreate
D/MainActivity: onStart
D/MainActivity: onResume
1.3 Implementeer levenscyclus-callbacks in SecondActivity
Nu u de levenscyclus-callback-methoden voor MainActivity hebt geïmplementeerd, doet u hetzelfde voor SecondActivity.
- Open TweedeActiviteit.
- Voeg bovenaan de klasse een constante toe voor de LOG_TAG variabele:
private static final String LOG_TAG = SecondActivity.class.getSimpleName();
- Voeg de levenscyclus-callbacks en logboekinstructies toe aan de tweede activiteit. (U kunt de callback-methoden vanuit MainActivity kopiëren en plakken.)
- Voeg een loginstructie toe aan de returnReply() -methode net vóór de finish() -methode:
Log.d(LOG_TAG, "End SecondActivity");
1.4 Bekijk het logboek terwijl de app draait**
- Voer uw app uit.
- Klik op het tabblad Logcat onder aan Android Studio om het Logcat-venster weer te geven.
- Voer Activiteit in het zoekvak in. De Android-logcat kan erg lang en rommelig zijn. Omdat de variabele LOG_TAG in elke klasse de woorden MainActivity of SecondActivity bevat, kunt u met dit trefwoord het logboek alleen filteren op de dingen waarin u geïnteresseerd bent.
Experimenteer met uw app en houd er rekening mee dat de levenscyclusgebeurtenissen die plaatsvinden als reactie op verschillende acties. Probeer vooral deze dingen:
- Gebruik de app normaal (stuur een bericht, antwoord met een ander bericht).
- Gebruik de knop Terug om terug te gaan van de tweede activiteit naar de hoofdactiviteit.
- Gebruik de pijl-omhoog in de app-balk om terug te gaan van de tweede activiteit naar de hoofdactiviteit.
- Draai het apparaat op verschillende tijdstippen in uw app op zowel de hoofd- als de tweede activiteit en kijk wat er * in het logboek en op het scherm gebeurt.
- Druk op de overzichtsknop (de vierkante knop rechts van Home) en sluit de app (tik op de X).
- Keer terug naar het startscherm en start uw app opnieuw.
TIP: Als u uw app in een emulator uitvoert, kunt u rotatie simuleren met Control+F11 of Control+Function+F11.
Taak 1 oplossingscode
De volgende codefragmenten tonen de oplossingscode voor de eerste taak.
Hoofdactiviteit
De volgende codefragmenten tonen de toegevoegde code in MainActivity, maar niet de hele klasse.
De onCreate()-methode:
@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 andere levenscyclusmethoden:
@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");
}
Tweede activiteit
De volgende codefragmenten tonen de toegevoegde code in SecondActivity, maar niet de hele klasse.
Aan de top van de SecondActivity-klasse:
private static final String LOG_TAG = SecondActivity.class.getSimpleName();
De returnReply()-methode:
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 andere levenscyclusmethoden:
Hetzelfde als voor MainActivity hierboven.
4. 4. Taak 2: Bewaar en herstel de status van het activiteitsexemplaar
Afhankelijk van de systeembronnen en het gebruikersgedrag kan elke activiteit in uw app veel vaker worden vernietigd en gereconstrueerd dan u zou denken.
Je hebt dit gedrag misschien opgemerkt in de laatste sectie toen je het apparaat of de emulator draaide. Het roteren van het apparaat is een voorbeeld van een wijziging in de apparaatconfiguratie. Hoewel rotatie de meest voorkomende is, resulteren alle configuratiewijzigingen erin dat de huidige activiteit wordt vernietigd en opnieuw wordt aangemaakt alsof deze nieuw is. Als u in uw code geen rekening houdt met dit gedrag, kan uw activiteitslay-out terugkeren naar de standaardweergave en oorspronkelijke waarden wanneer er een configuratiewijziging plaatsvindt, en kunnen uw gebruikers hun plaats, hun gegevens of de status van hun voortgang in de code kwijtraken. jouw app.
De status van elke activiteit wordt opgeslagen als een set sleutel-waardeparen in een bundelobject dat de activiteitsinstancestatus wordt genoemd. Het systeem slaat standaardstatusinformatie op in de instantiestatusbundel net voordat de activiteit wordt gestopt, en geeft die bundel door aan de nieuwe activiteitsinstantie om te herstellen.
Om te voorkomen dat gegevens in een activiteit verloren gaan wanneer deze onverwachts worden vernietigd en opnieuw worden gemaakt, moet u de methode onSaveInstanceState() implementeren. Het systeem roept deze methode aan voor uw activiteit (tussen onPause() en onStop()) wanneer de mogelijkheid bestaat dat de activiteit wordt vernietigd en opnieuw wordt aangemaakt.
De gegevens die u in de exemplaarstatus opslaat, zijn alleen specifiek voor dit exemplaar van deze specifieke activiteit tijdens de huidige app-sessie. Wanneer u een nieuwe app-sessie stopt en opnieuw start, gaat de status van het activiteitsexemplaar verloren en keert de activiteit terug naar de standaardweergave. Als u gebruikersgegevens tussen app-sessies moet opslaan, gebruik dan gedeelde voorkeuren of een database. Beide leer je in een later practicum.
2.1 Bewaar de status van de activiteitsinstantie met onSaveInstanceState()
Het is je misschien opgevallen dat het draaien van het apparaat helemaal geen invloed heeft op de status van de tweede activiteit. Dit komt omdat de lay-out en status van de tweede activiteit worden gegenereerd op basis van de lay-out en de intentie die deze heeft geactiveerd. Zelfs als de activiteit opnieuw wordt gemaakt, is de intentie er nog steeds en worden de gegevens in die intentie nog steeds gebruikt telkens wanneer de methode onCreate() in de tweede activiteit wordt aangeroepen.
Bovendien zult u merken dat in elke activiteit alle tekst die u in EditText-elementen voor berichten of antwoorden hebt getypt, behouden blijft, zelfs als het apparaat wordt gedraaid. Dit komt omdat de statusinformatie van sommige View-elementen in uw lay-out automatisch wordt opgeslagen bij configuratiewijzigingen, en de huidige waarde van een EditText is een van die gevallen.
De enige activiteitsstatus waarin u geïnteresseerd bent, zijn dus de TextView-elementen voor de antwoordkop en de antwoordtekst in de hoofdactiviteit. Beide TextView-elementen zijn standaard onzichtbaar; ze verschijnen pas als je vanuit de tweede activiteit een bericht terugstuurt naar de hoofdactiviteit.
In deze taak voegt u code toe om de instantiestatus van deze twee TextView-elementen te behouden met behulp van onSaveInstanceState().
- Open Hoofdactiviteit.
- Voeg deze skeletimplementatie van onSaveInstanceState() toe aan de activiteit, of gebruik Code > Override Methods om een skeletoverschrijving in te voegen.
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
}
- Controleer of de header momenteel zichtbaar is, en zo ja, plaats die zichtbaarheidsstatus in de state Bundle met de putBoolean() methode en de sleutel "reply_visible".
if (mReplyHeadTextView.getVisibility() == View.VISIBLE) {
outState.putBoolean("reply_visible", true);
}
Houd er rekening mee dat de antwoordkop en de tekst onzichtbaar zijn gemarkeerd totdat er een antwoord is van de tweede activiteit. Als de koptekst zichtbaar is, moeten er antwoordgegevens worden opgeslagen. Houd er rekening mee dat we alleen geïnteresseerd zijn in die zichtbaarheidsstatus; de feitelijke tekst van de koptekst hoeft niet te worden opgeslagen, omdat die tekst nooit verandert.
- Voeg binnen dezelfde cheque de antwoordtekst toe aan de bundel.
outState.putString("reply_text",mReplyTextView.getText().toString());
Als de header zichtbaar is, kunt u ervan uitgaan dat het antwoordbericht zelf ook zichtbaar is. U hoeft de huidige zichtbaarheidsstatus van het antwoordbericht niet te testen of op te slaan. Alleen de daadwerkelijke tekst van het bericht gaat naar de status Bundel met de sleutel "reply_text".
U slaat alleen de status op van de weergave-elementen die kunnen veranderen nadat de activiteit is gemaakt. De andere weergave-elementen in uw app (de EditText, de knop) kunnen op elk gewenst moment opnieuw worden gemaakt vanuit de standaardlay-out.
Houd er rekening mee dat het systeem de status van sommige View-elementen opslaat, zoals de inhoud van EditText.
2.2 Herstel de status van de activiteitsinstantie in onCreate()
Nadat u de activiteitsinstantiestatus heeft opgeslagen, moet u deze ook herstellen wanneer de activiteit opnieuw wordt gemaakt. U kunt dit doen in onCreate() of door de callback onRestoreInstanceState() te implementeren, die wordt aangeroepen na onStart() nadat de activiteit is gemaakt.
Meestal is onCreate() de betere plaats om de activiteitsstatus te herstellen, om ervoor te zorgen dat de gebruikersinterface, inclusief de status, zo snel mogelijk beschikbaar is. Het is soms handig om dit in onRestoreInstanceState() te doen nadat alle initialisatie is uitgevoerd, of om subklassen te laten beslissen of ze uw standaardimplementatie willen gebruiken.
- Voeg in de onCreate()-methode, nadat de View-variabelen zijn geïnitialiseerd met findViewById(), een test toe om er zeker van te zijn dat SaveInstanceState niet null is.
// 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) {
}
Wanneer uw activiteit is gemaakt, geeft het systeem de statusbundel als enige argument door aan onCreate(). De eerste keer dat onCreate() wordt aangeroepen en uw app start, is de bundel null: er is geen bestaande status de eerste keer dat uw app start. Bij daaropvolgende aanroepen van onCreate() wordt een bundel gevuld met de gegevens die u hebt opgeslagen in onSaveInstanceState().
- Haal binnen die controle de huidige zichtbaarheid (true of false) uit de bundel met de sleutel "reply_visible".
if (savedInstanceState != null) {
boolean isVisible =
savedInstanceState.getBoolean("reply_visible");
}
- Voeg een test toe onder die vorige regel voor de isVisible-variabele.
if (isVisible) {
}
Als er een antwoord_visible-sleutel in de statusbundel zit (en isVisible daarom waar is), moet u de status herstellen.
- Maak de header zichtbaar in de isVisible-test.
mReplyHeadTextView.setVisibility(View.VISIBLE);
- Haal het antwoordtekstbericht op uit de bundel met de sleutel "reply_text", en stel de antwoordtekstweergave in om die tekenreeks weer te geven.
mReplyTextView.setText(savedInstanceState.getString("reply_text"));
- Maak het antwoord TextView ook zichtbaar:
mReplyTextView.setVisibility(View.VISIBLE);
- Voer de app uit. Probeer het apparaat of de emulator te draaien om ervoor te zorgen dat het antwoordbericht (als dat er is) op het scherm blijft staan nadat de activiteit opnieuw is gemaakt.
Oplossingscode voor taak 2
De volgende codefragmenten tonen de oplossingscode voor deze taak.
Hoofdactiviteit
De volgende codefragmenten tonen de toegevoegde code in MainActivity, maar niet de hele klasse.
De onSaveInstanceState() methode:
@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());
}
}
De onCreate()-methode:
@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);
}
}
}
Het volledige project:
Android Studio-project: TwoActivitiesLifecycle
5. Codering
Uitdaging: Maak een eenvoudige boodschappenlijst-app met een hoofdactiviteit voor de lijst die de gebruiker aan het samenstellen is, en een tweede activiteit voor een lijst met veelvoorkomende boodschappen.
- De hoofdactiviteit moet de lijst bevatten die moet worden samengesteld, die uit tien lege TextView-elementen moet bestaan.
- Een knop Item toevoegen bij de hoofdactiviteit start een tweede activiteit die een lijst met veelgebruikte winkelartikelen bevat (kaas, rijst, appels, enzovoort). Gebruik knopelementen om de items weer te geven.
- Als u een item kiest, keert de gebruiker terug naar de hoofdactiviteit en wordt een lege TextView bijgewerkt met het gekozen item.
Gebruik een intentie om informatie van de ene activiteit naar de andere door te geven. Zorg ervoor dat de huidige status van het boodschappenlijstje wordt opgeslagen wanneer de gebruiker het apparaat draait.
6. Samenvatting
- De activiteitslevenscyclus is een reeks toestanden waar een activiteit doorheen migreert, beginnend bij de eerste creatie ervan en eindigend wanneer het Android-systeem de bronnen voor die activiteit terugwint.
- Terwijl de gebruiker van de ene activiteit naar de andere navigeert, en binnen en buiten uw app, beweegt elke activiteit zich tussen verschillende fasen in de activiteitslevenscyclus.
- Elke status in de activiteitslevenscyclus heeft een bijbehorende callback-methode die u kunt overschrijven in uw activiteitsklasse.
- De levenscyclusmethoden zijn onCreate(), onStart(), onPause(), onRestart(), onResume(), onStop(), onDestroy().
- Door een callback-methode voor de levenscyclus te overschrijven, kunt u gedrag toevoegen dat optreedt wanneer uw activiteit naar die status overgaat.
- U kunt skeleton-override-methoden toevoegen aan uw klassen in Android Studio met Code > Overschrijven.
- Wijzigingen in de apparaatconfiguratie, zoals rotatie, hebben tot gevolg dat de activiteit wordt vernietigd en opnieuw wordt aangemaakt alsof deze nieuw is.
- Een deel van de activiteitsstatus blijft behouden bij een configuratiewijziging, inclusief de huidige waarden van EditText-elementen. Voor alle overige gegevens dient u deze gegevens expliciet zelf op te slaan.
- Sla de status van de activiteitsinstantie op in de methode onSaveInstanceState().
- Gegevens over de instancestatus worden opgeslagen als eenvoudige sleutel/waarde-paren in een bundel. Gebruik de bundelmethoden om gegevens in de bundel te plaatsen en er weer uit te halen.
- Herstel de instantiestatus in onCreate(), wat de voorkeursmanier is, of onRestoreInstanceState(). Rug
1. Welkom
Dit praktische codelab maakt deel uit van Unit 1: Aan de slag met de cursus Android Developer Fundamentals (Versie 2). U haalt de meeste waarde uit deze cursus als u de codelabs op volgorde doorwerkt:
- Zie Codelabs for Android Developer Fundamentals (V2) voor de volledige lijst met codelabs in de cursus.
- Zie Android Developer Fundamentals (versie 2) voor meer informatie over de cursus, inclusief links naar alle concepthoofdstukken, apps en dia's.
Invoering
In dit practicum leer je meer over de levenscyclus van een activiteit. De levenscyclus is de reeks toestanden waarin een activiteit zich gedurende zijn gehele levensduur kan bevinden, vanaf het moment waarop deze wordt gemaakt tot het moment waarop deze wordt vernietigd en het systeem zijn hulpbronnen terugwint. Terwijl een gebruiker tussen activiteiten in uw app navigeert (en ook uw app in- en uitgaat), wisselen activiteiten tussen verschillende fasen in hun levenscyclus.
Elke fase in de levenscyclus van een activiteit heeft een bijbehorende callback-methode: onCreate(), onStart(), onPause(), enzovoort. Wanneer een activiteit van status verandert, wordt de bijbehorende callback-methode aangeroepen. Je hebt een van deze methoden al gezien: onCreate(). Door een van de levenscyclus-callback-methoden in uw activiteitsklassen te overschrijven, kunt u het standaardgedrag van de activiteit wijzigen als reactie op gebruikers- of systeemacties.
De activiteitsstatus kan ook veranderen als reactie op wijzigingen in de apparaatconfiguratie, bijvoorbeeld wanneer de gebruiker het apparaat van staand naar liggend draait. Wanneer deze configuratiewijzigingen plaatsvinden, wordt de activiteit vernietigd en opnieuw gemaakt in de standaardstatus, en kan de gebruiker de informatie kwijtraken die hij of zij in de activiteit heeft ingevoerd. Om verwarring bij uw gebruikers te voorkomen, is het belangrijk dat u uw app ontwikkelt om onverwacht gegevensverlies te voorkomen. Later in dit practicum experimenteer je met configuratiewijzigingen en leer je hoe je de status van een activiteit kunt behouden als reactie op wijzigingen in de apparaatconfiguratie en andere gebeurtenissen in de levenscyclus van een activiteit.
In dit practicum voegt u logboekverklaringen toe aan de TwoActivities-app en observeert u veranderingen in de levenscyclus van activiteiten terwijl u de app gebruikt. Vervolgens gaat u met deze wijzigingen aan de slag en onderzoekt u hoe u onder deze omstandigheden met gebruikersinvoer kunt omgaan.
Vereisten
Je zou in staat moeten zijn om:
- Maak en voer een app-project uit in Android Studio .
- Voeg logboekinstructies toe aan uw app en bekijk deze logboeken in het Logcat-venster.
- Begrijp en werk ermee met een activiteit en een intentie, en voel u op uw gemak bij de interactie ermee.
Wat je zult leren
- Hoe de activiteitslevenscyclus werkt.
- Wanneer een activiteit start, pauzeert, stopt en wordt vernietigd.
- Over de callback-methoden voor de levenscyclus die zijn gekoppeld aan activiteitswijzigingen.
- Het effect van acties (zoals configuratiewijzigingen) die kunnen resulteren in levenscyclusgebeurtenissen van activiteiten.
- Hoe u de activiteitsstatus kunt behouden tijdens levenscyclusgebeurtenissen.
Wat je gaat doen
- Voeg code uit het vorige practicum toe aan de TwoActivities -app om de verschillende callbacks voor de levenscyclus van activiteiten te implementeren en logboekinstructies op te nemen.
- Observeer de statusveranderingen terwijl uw app wordt uitgevoerd en terwijl u met elke activiteit in uw app communiceert.
- Pas uw app aan om de exemplaarstatus te behouden van een activiteit die onverwacht opnieuw wordt gemaakt als reactie op gebruikersgedrag of configuratiewijzigingen op het apparaat.
2. App-overzicht
In dit practicum voeg je iets toe aan de TwoActivities app. De app ziet er ongeveer hetzelfde uit en gedraagt zich ongeveer hetzelfde als in het laatste codelab. Het bevat twee activiteitsimplementaties en geeft de gebruiker de mogelijkheid om tussen deze te verzenden. De wijzigingen die u in dit practicum in de app aanbrengt, hebben geen invloed op het zichtbare gebruikersgedrag.
3. 3. Taak 1: levenscyclus-callbacks toevoegen aan TwoActivities
In deze taak implementeert u alle callback-methoden voor de activiteitslevenscyclus om berichten naar logcat af te drukken wanneer deze methoden worden aangeroepen. Met deze logboekberichten kunt u zien wanneer de levenscyclus van de activiteit van status verandert, en hoe deze wijzigingen in de levenscyclus van invloed zijn op uw app terwijl deze wordt uitgevoerd.
1.1 (Optioneel) Kopieer het TwoActivities-project
Voor de taken in dit practicum pas je het bestaande TwoActivities -project aan dat je in het laatste practicum hebt gebouwd. Als u het vorige TwoActivities-project liever intact wilt houden, volgt u de stappen in Bijlage: Hulpprogramma's om een kopie van het project te maken.
1.2 Implementeer callbacks in MainActivity
- Open het TwoActivities-project in Android Studio en open MainActivity in het paneel Project > Android.
- Voeg in de methode onCreate() de volgende loginstructies toe:
Log.d(LOG_TAG, "-------");
Log.d(LOG_TAG, "onCreate");
- Voeg een overschrijving toe voor de onStart() callback, met een verklaring voor het logboek voor die gebeurtenis:
@Override
public void onStart(){
super.onStart();
Log.d(LOG_TAG, "onStart");
}
Voor een snelkoppeling selecteert u Code > Methoden negeren in Android Studio. Er verschijnt een dialoogvenster met alle mogelijke methoden die u in uw klas kunt overschrijven. Als u een of meer callback-methoden uit de lijst kiest, wordt een volledige sjabloon voor die methoden ingevoegd, inclusief de vereiste aanroep naar de superklasse.
- Gebruik de methode onStart() als sjabloon om de levenscycluscallbacks onPause(), onRestart(), onResume(), onStop() en onDestroy() te implementeren
Alle callback-methoden hebben dezelfde handtekeningen (behalve de naam). Als u onStart() kopieert en plakt om deze andere callback-methoden te maken, vergeet dan niet de inhoud bij te werken om de juiste methode in de superklasse aan te roepen, en om de juiste methode te loggen.
- Voer uw app uit.
- Klik op het tabblad Logcat onder aan Android Studio om het Logcat-venster weer te geven. U zou drie logberichten moeten zien die de drie levenscyclusstatussen weergeven waar de activiteit doorheen is gegaan toen deze begon:
D/MainActivity: -------
D/MainActivity: onCreate
D/MainActivity: onStart
D/MainActivity: onResume
1.3 Implementeer levenscyclus-callbacks in SecondActivity
Nu u de levenscyclus-callback-methoden voor MainActivity hebt geïmplementeerd, doet u hetzelfde voor SecondActivity.
- Open TweedeActiviteit.
- Voeg bovenaan de klasse een constante toe voor de LOG_TAG variabele:
private static final String LOG_TAG = SecondActivity.class.getSimpleName();
- Voeg de levenscyclus-callbacks en logboekinstructies toe aan de tweede activiteit. (U kunt de callback-methoden vanuit MainActivity kopiëren en plakken.)
- Voeg een loginstructie toe aan de returnReply() -methode net vóór de finish() -methode:
Log.d(LOG_TAG, "End SecondActivity");
1.4 Bekijk het logboek terwijl de app draait**
- Voer uw app uit.
- Klik op het tabblad Logcat onder aan Android Studio om het Logcat-venster weer te geven.
- Voer Activiteit in het zoekvak in. De Android-logcat kan erg lang en rommelig zijn. Omdat de variabele LOG_TAG in elke klasse de woorden MainActivity of SecondActivity bevat, kunt u met dit trefwoord het logboek alleen filteren op de dingen waarin u geïnteresseerd bent.
Experimenteer met uw app en houd er rekening mee dat de levenscyclusgebeurtenissen die plaatsvinden als reactie op verschillende acties. Probeer vooral deze dingen:
- Gebruik de app normaal (stuur een bericht, antwoord met een ander bericht).
- Gebruik de knop Terug om terug te gaan van de tweede activiteit naar de hoofdactiviteit.
- Gebruik de pijl-omhoog in de app-balk om terug te gaan van de tweede activiteit naar de hoofdactiviteit.
- Draai het apparaat op verschillende tijdstippen in uw app op zowel de hoofd- als de tweede activiteit en kijk wat er * in het logboek en op het scherm gebeurt.
- Druk op de overzichtsknop (de vierkante knop rechts van Home) en sluit de app (tik op de X).
- Keer terug naar het startscherm en start uw app opnieuw.
TIP: Als u uw app in een emulator uitvoert, kunt u rotatie simuleren met Control+F11 of Control+Function+F11.
Taak 1 oplossingscode
De volgende codefragmenten tonen de oplossingscode voor de eerste taak.
Hoofdactiviteit
De volgende codefragmenten tonen de toegevoegde code in MainActivity, maar niet de hele klasse.
De onCreate()-methode:
@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 andere levenscyclusmethoden:
@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");
}
Tweede activiteit
De volgende codefragmenten tonen de toegevoegde code in SecondActivity, maar niet de hele klasse.
Aan de top van de SecondActivity-klasse:
private static final String LOG_TAG = SecondActivity.class.getSimpleName();
De returnReply()-methode:
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 andere levenscyclusmethoden:
Hetzelfde als voor MainActivity hierboven.
4. 4. Taak 2: Bewaar en herstel de status van het activiteitsexemplaar
Afhankelijk van de systeembronnen en het gebruikersgedrag kan elke activiteit in uw app veel vaker worden vernietigd en gereconstrueerd dan u zou denken.
Je hebt dit gedrag misschien opgemerkt in de laatste sectie toen je het apparaat of de emulator draaide. Het roteren van het apparaat is een voorbeeld van een wijziging in de apparaatconfiguratie. Hoewel rotatie de meest voorkomende is, resulteren alle configuratiewijzigingen erin dat de huidige activiteit wordt vernietigd en opnieuw wordt aangemaakt alsof deze nieuw is. Als u in uw code geen rekening houdt met dit gedrag, kan uw activiteitslay-out terugkeren naar de standaardweergave en oorspronkelijke waarden wanneer er een configuratiewijziging plaatsvindt, en kunnen uw gebruikers hun plaats, hun gegevens of de status van hun voortgang in de code kwijtraken. jouw app.
De status van elke activiteit wordt opgeslagen als een set sleutel-waardeparen in een bundelobject dat de activiteitsinstancestatus wordt genoemd. Het systeem slaat standaardstatusinformatie op in de instantiestatusbundel net voordat de activiteit wordt gestopt, en geeft die bundel door aan de nieuwe activiteitsinstantie om te herstellen.
Om te voorkomen dat gegevens in een activiteit verloren gaan wanneer deze onverwachts worden vernietigd en opnieuw worden gemaakt, moet u de methode onSaveInstanceState() implementeren. Het systeem roept deze methode aan voor uw activiteit (tussen onPause() en onStop()) wanneer de mogelijkheid bestaat dat de activiteit wordt vernietigd en opnieuw wordt aangemaakt.
De gegevens die u in de exemplaarstatus opslaat, zijn alleen specifiek voor dit exemplaar van deze specifieke activiteit tijdens de huidige app-sessie. Wanneer u een nieuwe app-sessie stopt en opnieuw start, gaat de status van het activiteitsexemplaar verloren en keert de activiteit terug naar de standaardweergave. Als u gebruikersgegevens tussen app-sessies moet opslaan, gebruik dan gedeelde voorkeuren of een database. Beide leer je in een later practicum.
2.1 Bewaar de status van de activiteitsinstantie met onSaveInstanceState()
Het is je misschien opgevallen dat het draaien van het apparaat helemaal geen invloed heeft op de status van de tweede activiteit. Dit komt omdat de lay-out en status van de tweede activiteit worden gegenereerd op basis van de lay-out en de intentie die deze heeft geactiveerd. Zelfs als de activiteit opnieuw wordt gemaakt, is de intentie er nog steeds en worden de gegevens in die intentie nog steeds gebruikt telkens wanneer de methode onCreate() in de tweede activiteit wordt aangeroepen.
Bovendien zult u merken dat in elke activiteit alle tekst die u in EditText-elementen voor berichten of antwoorden hebt getypt, behouden blijft, zelfs als het apparaat wordt gedraaid. Dit komt omdat de statusinformatie van sommige View-elementen in uw lay-out automatisch wordt opgeslagen bij configuratiewijzigingen, en de huidige waarde van een EditText is een van die gevallen.
De enige activiteitsstatus waarin u geïnteresseerd bent, zijn dus de TextView-elementen voor de antwoordkop en de antwoordtekst in de hoofdactiviteit. Beide TextView-elementen zijn standaard onzichtbaar; ze verschijnen pas als je vanuit de tweede activiteit een bericht terugstuurt naar de hoofdactiviteit.
In deze taak voegt u code toe om de instantiestatus van deze twee TextView-elementen te behouden met behulp van onSaveInstanceState().
- Open Hoofdactiviteit.
- Voeg deze skeletimplementatie van onSaveInstanceState() toe aan de activiteit, of gebruik Code > Override Methods om een skeletoverschrijving in te voegen.
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
}
- Controleer of de header momenteel zichtbaar is, en zo ja, plaats die zichtbaarheidsstatus in de state Bundle met de putBoolean() methode en de sleutel "reply_visible".
if (mReplyHeadTextView.getVisibility() == View.VISIBLE) {
outState.putBoolean("reply_visible", true);
}
Houd er rekening mee dat de antwoordkop en de tekst onzichtbaar zijn gemarkeerd totdat er een antwoord is van de tweede activiteit. Als de koptekst zichtbaar is, moeten er antwoordgegevens worden opgeslagen. Houd er rekening mee dat we alleen geïnteresseerd zijn in die zichtbaarheidsstatus; de feitelijke tekst van de koptekst hoeft niet te worden opgeslagen, omdat die tekst nooit verandert.
- Voeg binnen dezelfde cheque de antwoordtekst toe aan de bundel.
outState.putString("reply_text",mReplyTextView.getText().toString());
Als de header zichtbaar is, kunt u ervan uitgaan dat het antwoordbericht zelf ook zichtbaar is. U hoeft de huidige zichtbaarheidsstatus van het antwoordbericht niet te testen of op te slaan. Alleen de daadwerkelijke tekst van het bericht gaat naar de status Bundel met de sleutel "reply_text".
U slaat alleen de status op van de weergave-elementen die kunnen veranderen nadat de activiteit is gemaakt. De andere weergave-elementen in uw app (de EditText, de knop) kunnen op elk gewenst moment opnieuw worden gemaakt vanuit de standaardlay-out.
Houd er rekening mee dat het systeem de status van sommige View-elementen opslaat, zoals de inhoud van EditText.
2.2 Herstel de status van de activiteitsinstantie in onCreate()
Nadat u de activiteitsinstantiestatus heeft opgeslagen, moet u deze ook herstellen wanneer de activiteit opnieuw wordt gemaakt. U kunt dit doen in onCreate() of door de callback onRestoreInstanceState() te implementeren, die wordt aangeroepen na onStart() nadat de activiteit is gemaakt.
Meestal is onCreate() de betere plaats om de activiteitsstatus te herstellen, om ervoor te zorgen dat de gebruikersinterface, inclusief de status, zo snel mogelijk beschikbaar is. Het is soms handig om dit in onRestoreInstanceState() te doen nadat alle initialisatie is uitgevoerd, of om subklassen te laten beslissen of ze uw standaardimplementatie willen gebruiken.
- Voeg in de onCreate()-methode, nadat de View-variabelen zijn geïnitialiseerd met findViewById(), een test toe om er zeker van te zijn dat SaveInstanceState niet null is.
// 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) {
}
Wanneer uw activiteit is gemaakt, geeft het systeem de statusbundel als enige argument door aan onCreate(). De eerste keer dat onCreate() wordt aangeroepen en uw app start, is de bundel null: er is geen bestaande status de eerste keer dat uw app start. Bij daaropvolgende aanroepen van onCreate() wordt een bundel gevuld met de gegevens die u hebt opgeslagen in onSaveInstanceState().
- Haal binnen die controle de huidige zichtbaarheid (true of false) uit de bundel met de sleutel "reply_visible".
if (savedInstanceState != null) {
boolean isVisible =
savedInstanceState.getBoolean("reply_visible");
}
- Voeg een test toe onder die vorige regel voor de isVisible-variabele.
if (isVisible) {
}
Als er een antwoord_visible-sleutel in de statusbundel zit (en isVisible daarom waar is), moet u de status herstellen.
- Maak de header zichtbaar in de isVisible-test.
mReplyHeadTextView.setVisibility(View.VISIBLE);
- Haal het antwoordtekstbericht op uit de bundel met de sleutel "reply_text", en stel de antwoordtekstweergave in om die tekenreeks weer te geven.
mReplyTextView.setText(savedInstanceState.getString("reply_text"));
- Maak het antwoord TextView ook zichtbaar:
mReplyTextView.setVisibility(View.VISIBLE);
- Voer de app uit. Probeer het apparaat of de emulator te draaien om ervoor te zorgen dat het antwoordbericht (als dat er is) op het scherm blijft staan nadat de activiteit opnieuw is gemaakt.
Oplossingscode voor taak 2
De volgende codefragmenten tonen de oplossingscode voor deze taak.
Hoofdactiviteit
De volgende codefragmenten tonen de toegevoegde code in MainActivity, maar niet de hele klasse.
De onSaveInstanceState() methode:
@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());
}
}
De onCreate()-methode:
@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);
}
}
}
Het volledige project:
Android Studio-project: TwoActivitiesLifecycle
5. Codering
Uitdaging: Maak een eenvoudige boodschappenlijst-app met een hoofdactiviteit voor de lijst die de gebruiker aan het samenstellen is, en een tweede activiteit voor een lijst met veelvoorkomende boodschappen.
- De hoofdactiviteit moet de lijst bevatten die moet worden samengesteld, die uit tien lege TextView-elementen moet bestaan.
- Een knop Item toevoegen bij de hoofdactiviteit start een tweede activiteit die een lijst met veelgebruikte winkelartikelen bevat (kaas, rijst, appels, enzovoort). Gebruik knopelementen om de items weer te geven.
- Als u een item kiest, keert de gebruiker terug naar de hoofdactiviteit en wordt een lege TextView bijgewerkt met het gekozen item.
Gebruik een intentie om informatie van de ene activiteit naar de andere door te geven. Zorg ervoor dat de huidige status van het boodschappenlijstje wordt opgeslagen wanneer de gebruiker het apparaat draait.
6. Samenvatting
- De activiteitslevenscyclus is een reeks toestanden waar een activiteit doorheen migreert, beginnend bij de eerste creatie ervan en eindigend wanneer het Android-systeem de bronnen voor die activiteit terugwint.
- Terwijl de gebruiker van de ene activiteit naar de andere navigeert, en binnen en buiten uw app, beweegt elke activiteit zich tussen verschillende fasen in de activiteitslevenscyclus.
- Elke status in de activiteitslevenscyclus heeft een bijbehorende callback-methode die u kunt overschrijven in uw activiteitsklasse.
- De levenscyclusmethoden zijn onCreate(), onStart(), onPause(), onRestart(), onResume(), onStop(), onDestroy().
- Door een callback-methode voor de levenscyclus te overschrijven, kunt u gedrag toevoegen dat optreedt wanneer uw activiteit naar die status overgaat.
- U kunt skeleton-override-methoden toevoegen aan uw klassen in Android Studio met Code > Overschrijven.
- Wijzigingen in de apparaatconfiguratie, zoals rotatie, hebben tot gevolg dat de activiteit wordt vernietigd en opnieuw wordt aangemaakt alsof deze nieuw is.
- Een deel van de activiteitsstatus blijft behouden bij een configuratiewijziging, inclusief de huidige waarden van EditText-elementen. Voor alle overige gegevens dient u deze gegevens expliciet zelf op te slaan.
- Sla de status van de activiteitsinstantie op in de methode onSaveInstanceState().
- Gegevens over de instancestatus worden opgeslagen als eenvoudige sleutel/waarde-paren in een bundel. Gebruik de bundelmethoden om gegevens in de bundel te plaatsen en er weer uit te halen.
- Herstel de instantiestatus in onCreate(), wat de voorkeursmanier is, of onRestoreInstanceState(). Rug
1. Welkom
Dit praktische codelab maakt deel uit van Unit 1: Aan de slag met de cursus Android Developer Fundamentals (Versie 2). U haalt de meeste waarde uit deze cursus als u de codelabs op volgorde doorwerkt:
- Zie Codelabs for Android Developer Fundamentals (V2) voor de volledige lijst met codelabs in de cursus.
- Zie Android Developer Fundamentals (versie 2) voor meer informatie over de cursus, inclusief links naar alle concepthoofdstukken, apps en dia's.
Invoering
In dit practicum leer je meer over de levenscyclus van een activiteit. De levenscyclus is de reeks toestanden waarin een activiteit zich gedurende zijn gehele levensduur kan bevinden, vanaf het moment waarop deze wordt gemaakt tot het moment waarop deze wordt vernietigd en het systeem zijn hulpbronnen terugwint. Terwijl een gebruiker tussen activiteiten in uw app navigeert (en ook uw app in- en uitgaat), wisselen activiteiten tussen verschillende fasen in hun levenscyclus.
Elke fase in de levenscyclus van een activiteit heeft een bijbehorende callback-methode: onCreate(), onStart(), onPause(), enzovoort. Wanneer een activiteit van status verandert, wordt de bijbehorende callback-methode aangeroepen. Je hebt een van deze methoden al gezien: onCreate(). Door een van de levenscyclus-callback-methoden in uw activiteitsklassen te overschrijven, kunt u het standaardgedrag van de activiteit wijzigen als reactie op gebruikers- of systeemacties.
De activiteitsstatus kan ook veranderen als reactie op wijzigingen in de apparaatconfiguratie, bijvoorbeeld wanneer de gebruiker het apparaat van staand naar liggend draait. Wanneer deze configuratiewijzigingen plaatsvinden, wordt de activiteit vernietigd en opnieuw gemaakt in de standaardstatus, en kan de gebruiker de informatie kwijtraken die hij of zij in de activiteit heeft ingevoerd. Om verwarring bij uw gebruikers te voorkomen, is het belangrijk dat u uw app ontwikkelt om onverwacht gegevensverlies te voorkomen. Later in dit practicum experimenteer je met configuratiewijzigingen en leer je hoe je de status van een activiteit kunt behouden als reactie op wijzigingen in de apparaatconfiguratie en andere gebeurtenissen in de levenscyclus van een activiteit.
In dit practicum voegt u logboekverklaringen toe aan de TwoActivities-app en observeert u veranderingen in de levenscyclus van activiteiten terwijl u de app gebruikt. Vervolgens gaat u met deze wijzigingen aan de slag en onderzoekt u hoe u onder deze omstandigheden met gebruikersinvoer kunt omgaan.
Vereisten
Je zou in staat moeten zijn om:
- Maak en voer een app-project uit in Android Studio .
- Voeg logboekinstructies toe aan uw app en bekijk deze logboeken in het Logcat-venster.
- Begrijp en werk ermee met een activiteit en een intentie, en voel u op uw gemak bij de interactie ermee.
Wat je zult leren
- Hoe de activiteitslevenscyclus werkt.
- Wanneer een activiteit start, pauzeert, stopt en wordt vernietigd.
- Over de callback-methoden voor de levenscyclus die zijn gekoppeld aan activiteitswijzigingen.
- Het effect van acties (zoals configuratiewijzigingen) die kunnen resulteren in levenscyclusgebeurtenissen van activiteiten.
- Hoe u de activiteitsstatus kunt behouden tijdens levenscyclusgebeurtenissen.
Wat je gaat doen
- Voeg code uit het vorige practicum toe aan de TwoActivities -app om de verschillende callbacks voor de levenscyclus van activiteiten te implementeren en logboekinstructies op te nemen.
- Observeer de statusveranderingen terwijl uw app wordt uitgevoerd en terwijl u met elke activiteit in uw app communiceert.
- Pas uw app aan om de exemplaarstatus te behouden van een activiteit die onverwacht opnieuw wordt gemaakt als reactie op gebruikersgedrag of configuratiewijzigingen op het apparaat.
2. App-overzicht
In dit practicum voeg je iets toe aan de TwoActivities app. De app ziet er ongeveer hetzelfde uit en gedraagt zich ongeveer hetzelfde als in het laatste codelab. Het bevat twee activiteitsimplementaties en geeft de gebruiker de mogelijkheid om tussen deze te verzenden. De wijzigingen die u in dit practicum in de app aanbrengt, hebben geen invloed op het zichtbare gebruikersgedrag.
3. 3. Taak 1: levenscyclus-callbacks toevoegen aan TwoActivities
In deze taak implementeert u alle callback-methoden voor de activiteitslevenscyclus om berichten naar logcat af te drukken wanneer deze methoden worden aangeroepen. Met deze logboekberichten kunt u zien wanneer de levenscyclus van de activiteit van status verandert, en hoe deze wijzigingen in de levenscyclus van invloed zijn op uw app terwijl deze wordt uitgevoerd.
1.1 (Optioneel) Kopieer het TwoActivities-project
Voor de taken in dit practicum pas je het bestaande TwoActivities -project aan dat je in het laatste practicum hebt gebouwd. Als u het vorige TwoActivities-project liever intact wilt houden, volgt u de stappen in Bijlage: Hulpprogramma's om een kopie van het project te maken.
1.2 Implementeer callbacks in MainActivity
- Open het TwoActivities-project in Android Studio en open MainActivity in het paneel Project > Android.
- Voeg in de methode onCreate() de volgende loginstructies toe:
Log.d(LOG_TAG, "-------");
Log.d(LOG_TAG, "onCreate");
- Voeg een overschrijving toe voor de onStart() callback, met een verklaring voor het logboek voor die gebeurtenis:
@Override
public void onStart(){
super.onStart();
Log.d(LOG_TAG, "onStart");
}
Voor een snelkoppeling selecteert u Code > Methoden negeren in Android Studio. Er verschijnt een dialoogvenster met alle mogelijke methoden die u in uw klas kunt overschrijven. Als u een of meer callback-methoden uit de lijst kiest, wordt een volledige sjabloon voor die methoden ingevoegd, inclusief de vereiste aanroep naar de superklasse.
- Gebruik de methode onStart() als sjabloon om de levenscycluscallbacks onPause(), onRestart(), onResume(), onStop() en onDestroy() te implementeren
Alle callback-methoden hebben dezelfde handtekeningen (behalve de naam). Als u onStart() kopieert en plakt om deze andere callback-methoden te maken, vergeet dan niet de inhoud bij te werken om de juiste methode in de superklasse aan te roepen, en om de juiste methode te loggen.
- Voer uw app uit.
- Klik op het tabblad Logcat onder aan Android Studio om het Logcat-venster weer te geven. U zou drie logberichten moeten zien die de drie levenscyclusstatussen weergeven waar de activiteit doorheen is gegaan toen deze begon:
D/MainActivity: -------
D/MainActivity: onCreate
D/MainActivity: onStart
D/MainActivity: onResume
1.3 Implementeer levenscyclus-callbacks in SecondActivity
Nu u de levenscyclus-callback-methoden voor MainActivity hebt geïmplementeerd, doet u hetzelfde voor SecondActivity.
- Open TweedeActiviteit.
- Voeg bovenaan de klasse een constante toe voor de LOG_TAG variabele:
private static final String LOG_TAG = SecondActivity.class.getSimpleName();
- Voeg de levenscyclus-callbacks en logboekinstructies toe aan de tweede activiteit. (U kunt de callback-methoden vanuit MainActivity kopiëren en plakken.)
- Voeg een loginstructie toe aan de returnReply() -methode net vóór de finish() -methode:
Log.d(LOG_TAG, "End SecondActivity");
1.4 Bekijk het logboek terwijl de app draait**
- Voer uw app uit.
- Klik op het tabblad Logcat onder aan Android Studio om het Logcat-venster weer te geven.
- Voer Activiteit in het zoekvak in. De Android-logcat kan erg lang en rommelig zijn. Omdat de variabele LOG_TAG in elke klasse de woorden MainActivity of SecondActivity bevat, kunt u met dit trefwoord het logboek alleen filteren op de dingen waarin u geïnteresseerd bent.
Experimenteer met uw app en houd er rekening mee dat de levenscyclusgebeurtenissen die plaatsvinden als reactie op verschillende acties. Probeer vooral deze dingen:
- Gebruik de app normaal (stuur een bericht, antwoord met een ander bericht).
- Gebruik de knop Terug om terug te gaan van de tweede activiteit naar de hoofdactiviteit.
- Gebruik de pijl-omhoog in de app-balk om terug te gaan van de tweede activiteit naar de hoofdactiviteit.
- Draai het apparaat op verschillende tijdstippen in uw app op zowel de hoofd- als de tweede activiteit en kijk wat er * in het logboek en op het scherm gebeurt.
- Druk op de overzichtsknop (de vierkante knop rechts van Home) en sluit de app (tik op de X).
- Keer terug naar het startscherm en start uw app opnieuw.
TIP: Als u uw app in een emulator uitvoert, kunt u rotatie simuleren met Control+F11 of Control+Function+F11.
Taak 1 oplossingscode
De volgende codefragmenten tonen de oplossingscode voor de eerste taak.
Hoofdactiviteit
De volgende codefragmenten tonen de toegevoegde code in MainActivity, maar niet de hele klasse.
De onCreate()-methode:
@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 andere levenscyclusmethoden:
@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");
}
Tweede activiteit
De volgende codefragmenten tonen de toegevoegde code in SecondActivity, maar niet de hele klasse.
Aan de top van de SecondActivity-klasse:
private static final String LOG_TAG = SecondActivity.class.getSimpleName();
De returnReply()-methode:
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 andere levenscyclusmethoden:
Hetzelfde als voor MainActivity hierboven.
4. 4. Taak 2: Bewaar en herstel de status van het activiteitsexemplaar
Afhankelijk van de systeembronnen en het gebruikersgedrag kan elke activiteit in uw app veel vaker worden vernietigd en gereconstrueerd dan u zou denken.
Je hebt dit gedrag misschien opgemerkt in de laatste sectie toen je het apparaat of de emulator draaide. Het roteren van het apparaat is een voorbeeld van een wijziging in de apparaatconfiguratie. Hoewel rotatie de meest voorkomende is, resulteren alle configuratiewijzigingen erin dat de huidige activiteit wordt vernietigd en opnieuw wordt aangemaakt alsof deze nieuw is. Als u in uw code geen rekening houdt met dit gedrag, kan uw activiteitslay-out terugkeren naar de standaardweergave en oorspronkelijke waarden wanneer er een configuratiewijziging plaatsvindt, en kunnen uw gebruikers hun plaats, hun gegevens of de status van hun voortgang in de code kwijtraken. jouw app.
De status van elke activiteit wordt opgeslagen als een set sleutel-waardeparen in een bundelobject dat de activiteitsinstancestatus wordt genoemd. Het systeem slaat standaardstatusinformatie op in de instantiestatusbundel net voordat de activiteit wordt gestopt, en geeft die bundel door aan de nieuwe activiteitsinstantie om te herstellen.
Om te voorkomen dat gegevens in een activiteit verloren gaan wanneer deze onverwachts worden vernietigd en opnieuw worden gemaakt, moet u de methode onSaveInstanceState() implementeren. Het systeem roept deze methode aan voor uw activiteit (tussen onPause() en onStop()) wanneer de mogelijkheid bestaat dat de activiteit wordt vernietigd en opnieuw wordt aangemaakt.
De gegevens die u in de exemplaarstatus opslaat, zijn alleen specifiek voor dit exemplaar van deze specifieke activiteit tijdens de huidige app-sessie. Wanneer u een nieuwe app-sessie stopt en opnieuw start, gaat de status van het activiteitsexemplaar verloren en keert de activiteit terug naar de standaardweergave. Als u gebruikersgegevens tussen app-sessies moet opslaan, gebruik dan gedeelde voorkeuren of een database. Beide leer je in een later practicum.
2.1 Bewaar de status van de activiteitsinstantie met onSaveInstanceState()
Het is je misschien opgevallen dat het draaien van het apparaat helemaal geen invloed heeft op de status van de tweede activiteit. Dit komt omdat de lay-out en status van de tweede activiteit worden gegenereerd op basis van de lay-out en de intentie die deze heeft geactiveerd. Zelfs als de activiteit opnieuw wordt gemaakt, is de intentie er nog steeds en worden de gegevens in die intentie nog steeds gebruikt telkens wanneer de methode onCreate() in de tweede activiteit wordt aangeroepen.
Bovendien zult u merken dat in elke activiteit alle tekst die u in EditText-elementen voor berichten of antwoorden hebt getypt, behouden blijft, zelfs als het apparaat wordt gedraaid. Dit komt omdat de statusinformatie van sommige View-elementen in uw lay-out automatisch wordt opgeslagen bij configuratiewijzigingen, en de huidige waarde van een EditText is een van die gevallen.
De enige activiteitsstatus waarin u geïnteresseerd bent, zijn dus de TextView-elementen voor de antwoordkop en de antwoordtekst in de hoofdactiviteit. Beide TextView-elementen zijn standaard onzichtbaar; ze verschijnen pas als je vanuit de tweede activiteit een bericht terugstuurt naar de hoofdactiviteit.
In deze taak voegt u code toe om de instantiestatus van deze twee TextView-elementen te behouden met behulp van onSaveInstanceState().
- Open Hoofdactiviteit.
- Voeg deze skeletimplementatie van onSaveInstanceState() toe aan de activiteit, of gebruik Code > Override Methods om een skeletoverschrijving in te voegen.
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
}
- Controleer of de header momenteel zichtbaar is, en zo ja, plaats die zichtbaarheidsstatus in de state Bundle met de putBoolean() methode en de sleutel "reply_visible".
if (mReplyHeadTextView.getVisibility() == View.VISIBLE) {
outState.putBoolean("reply_visible", true);
}
Houd er rekening mee dat de antwoordkop en de tekst onzichtbaar zijn gemarkeerd totdat er een antwoord is van de tweede activiteit. Als de koptekst zichtbaar is, moeten er antwoordgegevens worden opgeslagen. Houd er rekening mee dat we alleen geïnteresseerd zijn in die zichtbaarheidsstatus; de feitelijke tekst van de koptekst hoeft niet te worden opgeslagen, omdat die tekst nooit verandert.
- Voeg binnen dezelfde cheque de antwoordtekst toe aan de bundel.
outState.putString("reply_text",mReplyTextView.getText().toString());
Als de header zichtbaar is, kunt u ervan uitgaan dat het antwoordbericht zelf ook zichtbaar is. U hoeft de huidige zichtbaarheidsstatus van het antwoordbericht niet te testen of op te slaan. Alleen de daadwerkelijke tekst van het bericht gaat naar de status Bundel met de sleutel "reply_text".
U slaat alleen de status op van de weergave-elementen die kunnen veranderen nadat de activiteit is gemaakt. De andere weergave-elementen in uw app (de EditText, de knop) kunnen op elk gewenst moment opnieuw worden gemaakt vanuit de standaardlay-out.
Houd er rekening mee dat het systeem de status van sommige View-elementen opslaat, zoals de inhoud van EditText.
2.2 Herstel de status van de activiteitsinstantie in onCreate()
Nadat u de activiteitsinstantiestatus heeft opgeslagen, moet u deze ook herstellen wanneer de activiteit opnieuw wordt gemaakt. U kunt dit doen in onCreate() of door de callback onRestoreInstanceState() te implementeren, die wordt aangeroepen na onStart() nadat de activiteit is gemaakt.
Meestal is onCreate() de betere plaats om de activiteitsstatus te herstellen, om ervoor te zorgen dat de gebruikersinterface, inclusief de status, zo snel mogelijk beschikbaar is. Het is soms handig om dit in onRestoreInstanceState() te doen nadat alle initialisatie is uitgevoerd, of om subklassen te laten beslissen of ze uw standaardimplementatie willen gebruiken.
- Voeg in de onCreate()-methode, nadat de View-variabelen zijn geïnitialiseerd met findViewById(), een test toe om er zeker van te zijn dat SaveInstanceState niet null is.
// 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) {
}
Wanneer uw activiteit is gemaakt, geeft het systeem de statusbundel als enige argument door aan onCreate(). De eerste keer dat onCreate() wordt aangeroepen en uw app start, is de bundel null: er is geen bestaande status de eerste keer dat uw app start. Bij daaropvolgende aanroepen van onCreate() wordt een bundel gevuld met de gegevens die u hebt opgeslagen in onSaveInstanceState().
- Haal binnen die controle de huidige zichtbaarheid (true of false) uit de bundel met de sleutel "reply_visible".
if (savedInstanceState != null) {
boolean isVisible =
savedInstanceState.getBoolean("reply_visible");
}
- Voeg een test toe onder die vorige regel voor de isVisible-variabele.
if (isVisible) {
}
Als er een antwoord_visible-sleutel in de statusbundel zit (en isVisible daarom waar is), moet u de status herstellen.
- Maak de header zichtbaar in de isVisible-test.
mReplyHeadTextView.setVisibility(View.VISIBLE);
- Haal het antwoordtekstbericht op uit de bundel met de sleutel "reply_text", en stel de antwoordtekstweergave in om die tekenreeks weer te geven.
mReplyTextView.setText(savedInstanceState.getString("reply_text"));
- Maak het antwoord TextView ook zichtbaar:
mReplyTextView.setVisibility(View.VISIBLE);
- Voer de app uit. Probeer het apparaat of de emulator te draaien om ervoor te zorgen dat het antwoordbericht (als dat er is) op het scherm blijft staan nadat de activiteit opnieuw is gemaakt.
Oplossingscode voor taak 2
De volgende codefragmenten tonen de oplossingscode voor deze taak.
Hoofdactiviteit
De volgende codefragmenten tonen de toegevoegde code in MainActivity, maar niet de hele klasse.
De onSaveInstanceState() methode:
@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());
}
}
De onCreate()-methode:
@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);
}
}
}
Het volledige project:
Android Studio-project: TwoActivitiesLifecycle
5. Codering
Uitdaging: Maak een eenvoudige boodschappenlijst-app met een hoofdactiviteit voor de lijst die de gebruiker aan het samenstellen is, en een tweede activiteit voor een lijst met veelvoorkomende boodschappen.
- De hoofdactiviteit moet de lijst bevatten die moet worden samengesteld, die uit tien lege TextView-elementen moet bestaan.
- Een knop Item toevoegen bij de hoofdactiviteit start een tweede activiteit die een lijst met veelgebruikte winkelartikelen bevat (kaas, rijst, appels, enzovoort). Gebruik knopelementen om de items weer te geven.
- Als u een item kiest, keert de gebruiker terug naar de hoofdactiviteit en wordt een lege TextView bijgewerkt met het gekozen item.
Gebruik een intentie om informatie van de ene activiteit naar de andere door te geven. Zorg ervoor dat de huidige status van het boodschappenlijstje wordt opgeslagen wanneer de gebruiker het apparaat draait.
6. Samenvatting
- De activiteitslevenscyclus is een reeks toestanden waar een activiteit doorheen migreert, beginnend bij de eerste creatie ervan en eindigend wanneer het Android-systeem de bronnen voor die activiteit terugwint.
- Terwijl de gebruiker van de ene activiteit naar de andere navigeert, en binnen en buiten uw app, beweegt elke activiteit zich tussen verschillende fasen in de activiteitslevenscyclus.
- Elke status in de activiteitslevenscyclus heeft een bijbehorende callback-methode die u kunt overschrijven in uw activiteitsklasse.
- De levenscyclusmethoden zijn onCreate(), onStart(), onPause(), onRestart(), onResume(), onStop(), onDestroy().
- Door een callback-methode voor de levenscyclus te overschrijven, kunt u gedrag toevoegen dat optreedt wanneer uw activiteit naar die status overgaat.
- U kunt skeleton-override-methoden toevoegen aan uw klassen in Android Studio met Code > Overschrijven.
- Wijzigingen in de apparaatconfiguratie, zoals rotatie, hebben tot gevolg dat de activiteit wordt vernietigd en opnieuw wordt aangemaakt alsof deze nieuw is.
- Een deel van de activiteitsstatus blijft behouden bij een configuratiewijziging, inclusief de huidige waarden van EditText-elementen. Voor alle overige gegevens dient u deze gegevens expliciet zelf op te slaan.
- Sla de status van de activiteitsinstantie op in de methode onSaveInstanceState().
- Gegevens over de instancestatus worden opgeslagen als eenvoudige sleutel/waarde-paren in een bundel. Gebruik de bundelmethoden om gegevens in de bundel te plaatsen en er weer uit te halen.
- Herstel de instantiestatus in onCreate(), wat de voorkeursmanier is, of onRestoreInstanceState(). Rug