Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
Activiteiten zijn een fundamentele bouwsteen van Android-toepassingen en kunnen bestaan in een aantal verschillende statussen. De levenscyclus van de activiteit begint met instantiëring en eindigt met vernietiging en bevat veel statussen ertussen. Wanneer de status van een activiteit verandert, wordt de juiste levenscyclusgebeurtenismethode aangeroepen, waarbij de activiteit op de hoogte wordt gebracht van de aanstaande statuswijziging en code kan uitvoeren om zich aan die wijziging aan te passen. In dit artikel wordt het verloop van activiteiten onderzocht en wordt uitgelegd welke verantwoordelijkheid een activiteit heeft tijdens elke overgang in de status om deel uit te maken van een goede, betrouwbare toepassing.
Overzicht van de levenscyclus van activiteiten
Activiteiten zijn een ongebruikelijk programmeerconcept dat specifiek is voor Android. Bij traditionele toepassingsontwikkeling is er meestal een statische hoofdmethode, die wordt uitgevoerd om de toepassing te starten. Met Android zijn de dingen echter anders; Android-toepassingen kunnen worden gestart via elke geregistreerde activiteit binnen een toepassing. In de praktijk hebben de meeste toepassingen alleen een specifieke activiteit die is opgegeven als het toegangspunt van de toepassing. Als een toepassing echter vastloopt of wordt beëindigd door het besturingssysteem, kan het besturingssysteem proberen de toepassing opnieuw op te starten bij de laatste geopende activiteit of ergens anders in de vorige activiteitsstack. Daarnaast kan het besturingssysteem activiteiten onderbreken wanneer ze niet actief zijn en ze vrijmaken als het onvoldoende geheugen heeft. Er moet zorgvuldig rekening mee worden gehouden dat de toepassing de status correct kan herstellen in het geval dat een activiteit opnieuw wordt gestart, met name als die activiteit afhankelijk is van gegevens van eerdere activiteiten.
De levenscyclus van activiteiten wordt geïmplementeerd als een verzameling methoden die het besturingssysteem aanroept gedurende de levenscyclus van een activiteit. Met deze methoden kunnen ontwikkelaars de functionaliteit implementeren die nodig is om te voldoen aan de vereisten voor status- en resourcebeheer van hun toepassingen.
Het is uiterst belangrijk dat de ontwikkelaar van de toepassing de vereisten van elke activiteit analyseert om te bepalen welke methoden beschikbaar worden gesteld door de levenscyclus van de activiteit. Als u dit niet doet, kan dit leiden tot instabiliteit van toepassingen, crashes, resource-bloat en mogelijk zelfs onderliggende instabiliteit van het besturingssysteem.
In dit hoofdstuk wordt de levenscyclus van activiteiten uitvoerig besproken, waaronder:
- Activiteitsstatussen
- Levenscyclusmethoden
- De status van een toepassing behouden
Deze sectie bevat ook een overzicht met praktische voorbeelden over het efficiënt opslaan van de status tijdens de levenscyclus van activiteiten. Aan het einde van dit hoofdstuk moet u inzicht hebben in de levenscyclus van activiteit en hoe u deze kunt ondersteunen in een Android-toepassing.
Levenscyclus van activiteit
De levenscyclus van Android-activiteiten bestaat uit een verzameling methoden die beschikbaar zijn in de activiteitsklasse die de ontwikkelaar een resourcebeheerframework biedt. Met dit framework kunnen ontwikkelaars voldoen aan de unieke statusbeheervereisten van elke activiteit binnen een toepassing en goed omgaan met resourcebeheer.
Activiteitsstatussen
Het Android-besturingssysteem beheert Activiteiten op basis van hun status. Dit helpt Android om activiteiten te identificeren die niet meer in gebruik zijn, waardoor het besturingssysteem geheugen en resources kan vrijmaken. In het volgende diagram ziet u de statussen die een activiteit tijdens de levensduur kan doorlopen:
Deze statussen kunnen als volgt worden onderverdeeld in vier hoofdgroepen:
Actief of Uitgevoerd, activiteiten worden als actief of uitgevoerd beschouwd wanneer ze zich op de voorgrond bevinden, ook wel de bovenkant van de activity stack genoemd. Dit wordt beschouwd als de hoogste prioriteitsactiviteit in Android en wordt daarom alleen door het besturingssysteem gedood in extreme situaties, bijvoorbeeld als de activiteit meer geheugen probeert te gebruiken dan beschikbaar is op het apparaat, omdat dit ertoe kan leiden dat de gebruikersinterface niet meer reageert.
Onderbroken : wanneer het apparaat in de slaapstand gaat of een activiteit nog steeds zichtbaar is, maar gedeeltelijk verborgen door een nieuwe, niet-volledige of transparante activiteit, wordt de activiteit beschouwd als onderbroken. Onderbroken activiteiten zijn nog actief, dat wil gezegd, ze houden alle staats- en lidgegevens bij en blijven gekoppeld aan de vensterbeheerder. Dit wordt beschouwd als de op een na hoogste prioriteitsactiviteit in Android en wordt daarom alleen gedood door het besturingssysteem als het doden van deze activiteit voldoet aan de resourcevereisten die nodig zijn om de actieve/actieve activiteit stabiel en responsief te houden.
Gestopt/achtergrond: activiteiten die volledig worden verborgen door een andere activiteit, worden beschouwd als gestopt of op de achtergrond. Gestopte activiteiten proberen hun status- en lidgegevens zo lang mogelijk te behouden, maar gestopte activiteiten worden beschouwd als de laagste prioriteit van de drie statussen. Als zodanig worden activiteiten in dit besturingssysteem eerst beëindigd om te voldoen aan de resourcevereisten van activiteiten met een hogere prioriteit.
Opnieuw opgestart : het is mogelijk dat een activiteit die overal is onderbroken tot gestopt in de levenscyclus, kan worden verwijderd uit het geheugen door Android. Als de gebruiker terug navigeert naar de activiteit, moet deze opnieuw worden gestart, hersteld worden naar de eerder opgeslagen staat en vervolgens aan de gebruiker worden weergegeven.
Activiteit Re-Creation als reactie op configuratiewijzigingen
Om zaken ingewikkelder te maken, gooit Android nog een sleutel in de mix met de naam Configuratiewijzigingen. Configuratiewijzigingen zijn snelle activiteitenvernietigings-/hercreatiecycli die optreden wanneer de configuratie van een activiteit verandert, zoals wanneer het apparaat wordt gedraaid (en de activiteit opnieuw moet worden ingebouwd in de liggende of staande modus), wanneer het toetsenbord wordt weergegeven (en de activiteit een kans krijgt om de grootte van het apparaat te wijzigen), of wanneer het apparaat in een dock wordt geplaatst, onder andere.
Configuratiewijzigingen veroorzaken nog steeds dezelfde wijzigingen in de activiteitsstatus die optreden tijdens het stoppen en opnieuw starten van een activiteit. Om ervoor te zorgen dat een toepassing reageert en goed presteert tijdens configuratiewijzigingen, is het echter belangrijk dat ze zo snel mogelijk worden verwerkt. Daarom heeft Android een specifieke API die kan worden gebruikt om de status te behouden tijdens configuratiewijzigingen. Dit behandelen we verderop in de sectie Managing State Throughout the Lifecycle.
Levenscyclusmethoden voor activiteiten
De Android SDK en het Xamarin.Android-framework bieden een krachtig model voor het beheren van de status van activiteiten binnen een toepassing. Wanneer de status van een activiteit wordt gewijzigd, wordt de activiteit gewaarschuwd door het besturingssysteem, dat specifieke methoden voor die activiteit aanroept. In het volgende diagram ziet u de volgende methoden met betrekking tot de levenscyclus van activiteiten:
Als ontwikkelaar kunt u statuswijzigingen afhandelen door deze methoden binnen een activiteit te overschrijven. Het is echter belangrijk om te weten dat alle levenscyclusmethoden worden aangeroepen op de UI-thread en het besturingssysteem blokkeert het volgende deel van de ui-werkzaamheden, zoals het verbergen van de huidige activiteit, het weergeven van een nieuwe activiteit, enzovoort. Daarom moet code in deze methoden zo kort mogelijk zijn om ervoor te zorgen dat een toepassing goed presteert. Alle langlopende taken moeten worden uitgevoerd op een achtergrondthread.
Laten we elk van deze levenscyclusmethoden en het gebruik ervan bekijken:
OnCreate
OnCreate is de eerste methode die moet worden aangeroepen wanneer een activiteit wordt gemaakt.
OnCreate wordt altijd overschreven om opstart initialisaties uit te voeren die mogelijk vereist zijn voor een activiteit, zoals:
- Weergaven maken
- Variabelen initialiseren
- Statische gegevens binden aan lijsten
OnCreate gebruikt een bundelparameter , een woordenlijst voor het opslaan en doorgeven van statusinformatie en objecten tussen activiteiten Als de bundel niet null is, geeft dit aan dat de activiteit opnieuw wordt opgestart en dat de status van het vorige exemplaar moet worden hersteld. De volgende code illustreert hoe u waarden ophaalt uit de bundel:
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
string intentString;
bool intentBool;
if (bundle != null)
{
intentString = bundle.GetString("myString");
intentBool = bundle.GetBoolean("myBool");
}
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.Main);
}
Zodra OnCreate dit heeft voltooid, zal Android OnStart aanroepen.
OnStart
OnStart wordt altijd aangeroepen door het systeem nadat OnCreate voltooid is. Activiteiten kunnen deze methode overschrijven als ze specifieke taken moeten uitvoeren voordat een activiteit zichtbaar wordt, zoals het vernieuwen van de huidige waarden van weergaven binnen de activiteit. Android OnResume wordt onmiddellijk na deze methode aangeroepen.
OnResume
Het systeem roept OnResume aan wanneer de activiteit gereed is om met de gebruiker te communiceren. Activiteiten moeten deze methode overschrijven om taken uit te voeren, zoals:
- Framesnelheden verhogen (een algemene taak in gameontwikkeling)
- Animaties starten
- Luisteren naar GPS-updates
- Relevante waarschuwingen of dialoogvensters weergeven
- Externe gebeurtenis-handlers aansluiten
In het volgende codefragment ziet u bijvoorbeeld hoe u de camera initialiseert:
protected override void OnResume()
{
base.OnResume(); // Always call the superclass first.
if (_camera==null)
{
// Do camera initializations here
}
}
OnResume is belangrijk omdat elke bewerking die in OnPause wordt uitgevoerd, moet worden teruggedraaid in OnResume, aangezien het de enige levenscyclusmethode is die gegarandeerd wordt uitgevoerd na OnPause wanneer de activiteit weer tot leven wordt gebracht.
OnPause
OnPause wordt aangeroepen wanneer het systeem de activiteit op het punt staat op de achtergrond te plaatsen of wanneer de activiteit gedeeltelijk wordt verborgen. Activiteiten moeten deze methode overschrijven als ze het volgende moeten doen:
Niet-opgeslagen wijzigingen doorvoeren in permanente gegevens
Andere objecten vernietigen of opschonen die resources verbruiken
Framesnelheden omlaag vouwen en animaties onderbreken
De registratie van externe gebeurtenis-handlers of meldingshandlers ongedaan maken (dat wil gezegd degenen die zijn gekoppeld aan een service). Dit moet worden gedaan om geheugenlekken van activiteiten te voorkomen.
Als de activiteit dialoogvensters of waarschuwingen heeft weergegeven, moeten ze ook worden opgeschoond met de
.Dismiss()methode.
Als voorbeeld laat het volgende codefragment de camera los, omdat de activiteit er niet gebruik van kan maken terwijl deze is onderbroken:
protected override void OnPause()
{
base.OnPause(); // Always call the superclass first
// Release the camera as other activities might need it
if (_camera != null)
{
_camera.Release();
_camera = null;
}
}
Er zijn twee mogelijke levenscyclusmethoden die worden aangeroepen na OnPause:
-
OnResumewordt aangeroepen wanneer de Activiteit naar de voorgrond wordt gebracht. -
OnStopwordt aangeroepen als de activiteit op de achtergrond wordt geplaatst.
OnStop
OnStop wordt aangeroepen wanneer de activiteit niet meer zichtbaar is voor de gebruiker. Dit gebeurt wanneer een van de volgende situaties optreedt:
- Er wordt een nieuwe activiteit gestart en deze activiteit overschaduwt de huidige activiteit.
- Er wordt een bestaande activiteit naar de voorgrond gebracht.
- De activiteit wordt vernietigd.
OnStop kan niet altijd worden aangeroepen in situaties met weinig geheugen, zoals wanneer Android gebrek heeft aan resources en de activiteit niet correct op de achtergrond kan plaatsen. Om deze reden is het het beste niet te vertrouwen op OnStop het oproepen van een Activity voor vernietiging. De volgende levenscyclusmethoden die hierna kunnen worden aangeroepen, zijn OnDestroy als de activiteit weggaat of OnRestart als de activiteit terugkomt om met de gebruiker te communiceren.
OnDestroy
OnDestroy is de laatste methode die wordt aangeroepen op een Activiteit-instance voordat het wordt vernietigd en volledig uit het geheugen wordt verwijderd. In extreme situaties kan Android het toepassingsproces beëindigen dat als host fungeert voor de activiteit, wat ertoe leidt OnDestroy dat deze niet wordt aangeroepen. De meeste activiteiten implementeren deze methode niet omdat de meeste opschoning en afsluiting zijn uitgevoerd in de OnPause en OnStop methoden. De OnDestroy-methode wordt doorgaans overschreven om langlopende taken op te schonen en zo te voorkomen dat er hulpbronnen gelekt kunnen worden. Een voorbeeld hiervan zijn achtergrondthreads die zijn gestart in OnCreate.
Er worden geen levenscyclusmethoden aangeroepen nadat de activiteit is vernietigd.
OnRestart
OnRestart wordt aangeroepen nadat uw activiteit is gestopt, voordat deze opnieuw wordt gestart. Een goed voorbeeld hiervan is wanneer de gebruiker op de startknop drukt tijdens een activiteit in de toepassing. Wanneer dit gebeurt, worden de OnPause en OnStop methoden aangeroepen en wordt de activiteit naar de achtergrond verplaatst, maar niet vernietigd. Als de gebruiker de toepassing vervolgens zou herstellen met behulp van taakbeheer of een vergelijkbare toepassing, roept Android de OnRestart methode van de activiteit aan.
Er zijn geen algemene richtlijnen voor het soort logica dat moet worden geïmplementeerd in OnRestart. Dit komt doordat OnStart altijd wordt aangeroepen, ongeacht of de activiteit wordt gemaakt of opnieuw wordt gestart, zodat alle resources die vereist zijn voor de activiteit moeten worden geïnitialiseerd in OnStart, in plaats OnRestartvan .
De volgende levenscyclusmethode die hierna OnRestart wordt aangeroepen, is OnStart.
Terug versus Home
Veel Android-apparaten hebben twee verschillende knoppen: een 'Terug'-knop en een 'Start'-knop. Een voorbeeld hiervan is te zien in de volgende schermopname van Android 4.0.3:
Er is een subtiel verschil tussen de twee knoppen, ook al lijken ze hetzelfde effect te hebben om een toepassing op de achtergrond te plaatsen. Wanneer een gebruiker op de knop Terug klikt, vertelt hij of zij Android heeft laten weten dat ze klaar zijn met de activiteit. Android vernietigt de activiteit. Als de gebruiker daarentegen op de knop Start klikt, wordt de activiteit alleen op de achtergrond geplaatst. Android beëindigt de activiteit niet.
Status beheren gedurende de hele levenscyclus
Wanneer een activiteit wordt gestopt of vernietigd, biedt het systeem de mogelijkheid om de status van de activiteit op te slaan voor latere rehydratatie. Deze opgeslagen status wordt de instantiestatus genoemd. Android biedt drie opties voor het opslaan van de instantiestatus tijdens de levenscyclus van activiteit:
Het opslaan van primitieve waarden in een
Dictionary, die Android gebruikt om de status te bewaren.Het maken van een aangepaste klasse die complexe waarden zoals bitmaps bevat. Android gebruikt deze aangepaste klasse om de status op te slaan.
De levenscyclus van de configuratiewijziging omzeilen en de volledige verantwoordelijkheid nemen voor het onderhouden van de toestand binnen de activiteit.
In deze handleiding worden de eerste twee opties behandeld.
Bundelstatus
De primaire optie voor het opslaan van de instantiestatus is het gebruik van een sleutel-waardewoordenlijstobject dat bekend staat als een bundel.
Herinner u zich dat wanneer een activiteit wordt gemaakt waarbij de OnCreate methode een bundel als parameter krijgt, deze bundel kan worden gebruikt om de statustoestand van de instantie te herstellen. Het wordt niet aanbevolen om een bundel te gebruiken voor complexere gegevens die niet snel of eenvoudig serialiseren naar sleutel-/waardeparen (zoals bitmaps); In plaats daarvan moet deze worden gebruikt voor eenvoudige waarden, zoals tekenreeksen.
Een activiteit biedt methoden voor het opslaan en ophalen van de instantiestatus in de bundel:
OnSaveInstanceState : dit wordt aangeroepen door Android wanneer de activiteit wordt vernietigd. Activiteiten kunnen deze methode implementeren als ze sleutel-/waardestatusitems moeten behouden.
OnRestoreInstanceState : dit wordt aangeroepen nadat de
OnCreatemethode is voltooid en biedt een andere mogelijkheid om de status van een activiteit te herstellen nadat de initialisatie is voltooid.
In het volgende diagram ziet u hoe deze methoden worden gebruikt:
OnSaveInstanceState
OnSaveInstanceState wordt aangeroepen als de activiteit wordt gestopt. Er wordt een bundelparameter ontvangen waarin de activiteit de status ervan kan opslaan. Wanneer een apparaat een configuratiewijziging ondervindt, kan een activiteit het Bundle object gebruiken dat wordt doorgegeven om de status van de activiteit te behouden door deze te overschrijven OnSaveInstanceState. Denk bijvoorbeeld aan de volgende code:
int c;
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);
this.SetContentView (Resource.Layout.SimpleStateView);
var output = this.FindViewById<TextView> (Resource.Id.outputText);
if (bundle != null) {
c = bundle.GetInt ("counter", -1);
} else {
c = -1;
}
output.Text = c.ToString ();
var incrementCounter = this.FindViewById<Button> (Resource.Id.incrementCounter);
incrementCounter.Click += (s,e) => {
output.Text = (++c).ToString();
};
}
Met de bovenstaande code wordt een geheel getal genaamd c verhoogd wanneer op een knop genaamd incrementCounter wordt geklikt, waarbij het resultaat wordt weergegeven in een TextView genaamd output. Wanneer een configuratiewijziging plaatsvindt, bijvoorbeeld wanneer het apparaat wordt geroteerd, verliest de bovenstaande code de waarde c omdat dit bundle zou zijn null, zoals wordt weergegeven in de onderstaande afbeelding:
Als u de waarde van c in dit voorbeeld wilt behouden, kan de Activiteit OnSaveInstanceState overschrijven en de waarde in de bundel opslaan, zoals hieronder wordt weergegeven:
protected override void OnSaveInstanceState (Bundle outState)
{
outState.PutInt ("counter", c);
base.OnSaveInstanceState (outState);
}
Wanneer het apparaat nu naar een nieuwe oriëntatie wordt gedraaid, wordt het gehele getal in de bundel opgeslagen en opgehaald met de regel:
c = bundle.GetInt ("counter", -1);
Opmerking
Het is belangrijk om altijd de basis-implementatie OnSaveInstanceState aan te roepen, zodat de status van de weergavehiërarchie ook kan worden opgeslagen.
Status weergeven
Het overschrijven van OnSaveInstanceState is een geschikt mechanisme voor het opslaan van tijdelijke gegevens in een Activiteit bij wijzigingen in de schermoriëntatie, zoals de teller in het bovenstaande voorbeeld. Bij de standaard implementatie wordt OnSaveInstanceState echter gezorgd voor het opslaan van tijdelijke gegevens in de gebruikersinterface voor elke weergave, zolang aan elke weergave een id is toegewezen. Stel dat een toepassing een EditText element heeft dat als volgt is gedefinieerd in XML:
<EditText android:id="@+id/myText"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
Omdat er een id aan het EditText-besturingselement is toegewezen, blijven de gegevens zichtbaar wanneer de gebruiker gegevens invoert en het apparaat draait, zoals hieronder wordt weergegeven.
OnRestoreInstanceState
OnRestoreInstanceState wordt hierna OnStartaangeroepen. Het biedt een activiteit de mogelijkheid om een status te herstellen die eerder is opgeslagen in een bundel tijdens de vorige OnSaveInstanceState. Dit is echter dezelfde bundel die wordt verstrekt aan OnCreate.
De volgende code laat zien hoe de status kan worden hersteld in OnRestoreInstanceState:
protected override void OnRestoreInstanceState(Bundle savedState)
{
base.OnRestoreInstanceState(savedState);
var myString = savedState.GetString("myString");
var myBool = savedState.GetBoolean("myBool");
}
Deze methode bestaat om enige flexibiliteit te bieden bij het herstellen van de status. Soms is het beter om te wachten totdat alle initialisaties worden uitgevoerd voordat de exemplaarstatus wordt hersteld. Daarnaast kan een subklasse van een bestaande activiteit alleen bepaalde waarden uit de instantiestatus herstellen. In veel gevallen is het niet nodig om OnRestoreInstanceState te wijzigen, omdat de meeste activiteiten hun toestand kunnen herstellen met behulp van de bundel die aan OnCreate is doorgegeven.
Voor een voorbeeld van het opslaan van de status met behulp van een Bundle, raadpleegt u de walkthrough - De status van de activiteit opslaan.
Bundelbeperkingen
Hoewel OnSaveInstanceState het eenvoudig is om tijdelijke gegevens op te slaan, zijn er enkele beperkingen:
Het wordt niet in alle gevallen genoemd. Als u bijvoorbeeld op Start of Terug drukt om een activiteit af te sluiten, zal
OnSaveInstanceStateniet worden aangeroepen.De bundel die via
OnSaveInstanceStatewordt doorgegeven, is niet ontworpen voor grote objecten zoals afbeeldingen. In het geval van grote objecten verdient het opslaan van het object van OnRetainNonConfigurationInstance de voorkeur, zoals hieronder wordt besproken.Gegevens die worden opgeslagen met behulp van de bundel, worden geserialiseerd, wat kan leiden tot vertragingen.
Bundelstatus is handig voor eenvoudige gegevens die niet veel geheugen gebruiken, terwijl niet-configuratie-exemplaargegevens nuttig zijn voor complexere gegevens of gegevens die duur zijn om op te halen, zoals bij een webservice-aanroep of een ingewikkelde databasequery. Gegevens van niet-configuratie-exemplaren worden indien nodig opgeslagen in een object. In de volgende sectie wordt een manier geïntroduceerd OnRetainNonConfigurationInstance om complexere gegevenstypen te behouden door configuratiewijzigingen.
Complexe gegevens behouden
Naast persistente gegevens in de bundel biedt Android ook ondersteuning voor het opslaan van gegevens door OnRetainNonConfigurationInstance te overschrijven en een exemplaar te retourneren van een Java.Lang.Object exemplaar dat de gegevens bevat die moeten worden bewaard. Er zijn twee primaire voordelen van het gebruik OnRetainNonConfigurationInstance om de status op te slaan:
Het geretourneerde
OnRetainNonConfigurationInstanceobject werkt goed met grotere, complexere gegevenstypen, omdat het geheugen dit object behoudt.De
OnRetainNonConfigurationInstancemethode wordt op aanvraag aangeroepen en alleen wanneer dat nodig is. Dit is voordeliger dan het gebruik van een handmatige cache.
Het gebruik OnRetainNonConfigurationInstance is geschikt voor scenario's waarbij het duur is om de gegevens meerdere keren op te halen, zoals in webserviceaanroepen. Denk bijvoorbeeld aan de volgende code waarmee Twitter wordt doorzocht:
public class NonConfigInstanceActivity : ListActivity
{
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);
SearchTwitter ("xamarin");
}
public void SearchTwitter (string text)
{
string searchUrl = String.Format("http://search.twitter.com/search.json?" + "q={0}&rpp=10&include_entities=false&" + "result_type=mixed", text);
var httpReq = (HttpWebRequest)HttpWebRequest.Create (new Uri (searchUrl));
httpReq.BeginGetResponse (new AsyncCallback (ResponseCallback), httpReq);
}
void ResponseCallback (IAsyncResult ar)
{
var httpReq = (HttpWebRequest)ar.AsyncState;
using (var httpRes = (HttpWebResponse)httpReq.EndGetResponse (ar)) {
ParseResults (httpRes);
}
}
void ParseResults (HttpWebResponse httpRes)
{
var s = httpRes.GetResponseStream ();
var j = (JsonObject)JsonObject.Load (s);
var results = (from result in (JsonArray)j ["results"] let jResult = result as JsonObject select jResult ["text"].ToString ()).ToArray ();
RunOnUiThread (() => {
PopulateTweetList (results);
});
}
void PopulateTweetList (string[] results)
{
ListAdapter = new ArrayAdapter<string> (this, Resource.Layout.ItemView, results);
}
}
Met deze code worden resultaten opgehaald van het web dat is opgemaakt als JSON, worden deze geparseerd en worden de resultaten vervolgens weergegeven in een lijst, zoals wordt weergegeven in de volgende schermopname:
Wanneer een configuratiewijziging plaatsvindt, bijvoorbeeld wanneer een apparaat wordt geroteerd, herhaalt de code het proces. Als u de oorspronkelijk opgehaalde resultaten opnieuw wilt gebruiken en geen onnodige, redundante netwerkoproepen wilt veroorzaken, kunnen OnRetainNonconfigurationInstance we de resultaten opslaan, zoals hieronder wordt weergegeven:
public class NonConfigInstanceActivity : ListActivity
{
TweetListWrapper _savedInstance;
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);
var tweetsWrapper = LastNonConfigurationInstance as TweetListWrapper;
if (tweetsWrapper != null) {
PopulateTweetList (tweetsWrapper.Tweets);
} else {
SearchTwitter ("xamarin");
}
public override Java.Lang.Object OnRetainNonConfigurationInstance ()
{
base.OnRetainNonConfigurationInstance ();
return _savedInstance;
}
...
void PopulateTweetList (string[] results)
{
ListAdapter = new ArrayAdapter<string> (this, Resource.Layout.ItemView, results);
_savedInstance = new TweetListWrapper{Tweets=results};
}
}
Wanneer het apparaat nu wordt geroteerd, worden de oorspronkelijke resultaten opgehaald uit de LastNonConfiguartionInstance eigenschap. In dit voorbeeld bestaan de resultaten uit een string[] met tweets. Aangezien OnRetainNonConfigurationInstance vereist dat een Java.Lang.Object retour wordt geretourneerd, wordt de string[] verpakt in een klasse die subklassen Java.Lang.Objectbevat, zoals hieronder wordt weergegeven:
class TweetListWrapper : Java.Lang.Object
{
public string[] Tweets { get; set; }
}
Bijvoorbeeld, als u probeert een TextView als het object dat wordt geretourneerd door OnRetainNonConfigurationInstance te gebruiken, zal de Activiteit lekken, zoals geïllustreerd door de onderstaande code.
TextView _textView;
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);
var tv = LastNonConfigurationInstance as TextViewWrapper;
if(tv != null) {
_textView = tv;
var parent = _textView.Parent as FrameLayout;
parent.RemoveView(_textView);
} else {
_textView = new TextView (this);
_textView.Text = "This will leak.";
}
SetContentView (_textView);
}
public override Java.Lang.Object OnRetainNonConfigurationInstance ()
{
base.OnRetainNonConfigurationInstance ();
return _textView;
}
In deze sectie hebben we geleerd hoe u eenvoudige statusgegevens kunt behouden met de Bundleen complexere gegevenstypen kunt behouden met OnRetainNonConfigurationInstance.
Samenvatting
De levenscyclus van Android-activiteiten biedt een krachtig framework voor statusbeheer van activiteiten binnen een toepassing, maar het kan lastig zijn om te begrijpen en implementeren. In dit hoofdstuk zijn de verschillende statussen geïntroduceerd die een activiteit tijdens de levensduur kan doorlopen, evenals de levenscyclusmethoden die aan deze statussen zijn gekoppeld. Vervolgens is er richtlijnen gegeven voor het soort logica dat in elk van deze methoden moet worden uitgevoerd.