Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Działania są podstawowym blokiem konstrukcyjnym aplikacji systemu Android i mogą istnieć w wielu różnych stanach. Cykl życia działania rozpoczyna się od utworzenia wystąpienia i kończy się zniszczeniem i obejmuje wiele stanów między nimi. Gdy działanie zmienia stan, wywoływana jest odpowiednia metoda zdarzenia cyklu życia, powiadamiając działanie zbliżającej się zmiany stanu i umożliwiając jej wykonanie kodu w celu dostosowania się do tej zmiany. W tym artykule opisano cykl życia działań i wyjaśniono odpowiedzialność działania na każdym z tych etapów zmian stanu w ramach dobrze działającej, niezawodnej aplikacji.
Przegląd cyklu życia działania
Działania to nietypowa koncepcja programowania specyficzna dla systemu Android. W tradycyjnym tworzeniu aplikacji zwykle jest wykonywana statyczna metoda główna, która jest wykonywana w celu uruchomienia aplikacji. Z androidem jednak rzeczy są różne; Aplikacje dla systemu Android można uruchamiać za pośrednictwem dowolnego zarejestrowanego działania w aplikacji. W praktyce większość aplikacji będzie mieć tylko określone działanie określone, które jest określone jako punkt wejścia aplikacji. Jeśli jednak aplikacja ulegnie awarii lub zostanie zakończona przez system operacyjny, system operacyjny może spróbować ponownie uruchomić aplikację w ostatnim otwartym działaniu lub gdziekolwiek indziej w poprzednim stosie działań. Ponadto system operacyjny może wstrzymać działania, gdy nie są aktywne, i odzyskać je, jeśli jest mało pamięci. Należy zachować ostrożność, aby umożliwić aplikacji poprawne przywrócenie stanu w przypadku ponownego uruchomienia działania, zwłaszcza jeśli to działanie zależy od danych z poprzednich działań.
Cykl życia działania jest implementowany jako kolekcja metod wywoływanych przez system operacyjny w całym cyklu życia działania. Te metody umożliwiają deweloperom zaimplementowanie funkcji niezbędnych do spełnienia wymagań dotyczących stanu i zarządzania zasobami aplikacji.
Dla dewelopera aplikacji niezwykle ważne jest analizowanie wymagań każdej aktywności w celu określenia, które z metod dostępnych w cyklu życia aktywności trzeba zaimplementować. Niepowodzenie w tym celu może spowodować niestabilność aplikacji, awarie, wzdęcie zasobu, a nawet niestabilność bazowego systemu operacyjnego.
W tym rozdziale szczegółowo omówiono cykl życia działania, w tym:
- Stany działań
- Metody cyklu życia
- Zachowywanie stanu aplikacji
Ta sekcja zawiera również przewodnik , który zawiera praktyczne przykłady dotyczące efektywnego zapisywania stanu podczas cyklu życia działania. Na koniec tego rozdziału należy poznać cykl życia działania i sposób jego obsługi w aplikacji dla systemu Android.
Cykl życia działania
Cykl życia działania systemu Android obejmuje kolekcję metod uwidocznionych w klasie Activity, która zapewnia deweloperowi strukturę zarządzania zasobami. Ta struktura umożliwia deweloperom spełnienie unikatowych wymagań dotyczących zarządzania stanem poszczególnych działań w aplikacji i prawidłowe zarządzanie zasobami.
Stany aktywności
System operacyjny Android arbitruje działania na podstawie ich stanu. Ułatwia to systemowi Android identyfikowanie działań, które nie są już używane, dzięki czemu system operacyjny może odzyskać pamięć i zasoby. Na poniższym diagramie przedstawiono stany, przez które działanie może przechodzić w okresie jego istnienia:
Te stany można podzielić na 4 główne grupy w następujący sposób:
Aktywne lub uruchomione — działania są uznawane za aktywne lub uruchomione, jeśli znajdują się na pierwszym planie, znane również jako szczyt stosu działań. Jest to uważane za działanie o najwyższym priorytecie w systemie Android i w związku z tym zostanie zabite tylko przez system operacyjny w skrajnych sytuacjach, na przykład jeśli działanie próbuje użyć więcej pamięci niż jest dostępne na urządzeniu, ponieważ może to spowodować, że interfejs użytkownika przestanie odpowiadać.
Wstrzymano — gdy urządzenie przejdzie w stan uśpienia lub działanie jest nadal widoczne, ale częściowo ukryte przez nową, niezwiązaną z pełnym rozmiarem lub przezroczystą aktywność, działanie jest uznawane za wstrzymane. Wstrzymane działania są nadal aktywne, czyli utrzymują wszystkie informacje o stanie i członkach oraz pozostają dołączone do menedżera okien. Jest to uważane za drugie działanie o najwyższym priorytecie w systemie Android i, w związku z tym, zostanie zabite tylko przez system operacyjny, jeśli zabicie tego działania spełni wymagania dotyczące zasobów wymaganych do utrzymania stabilnej i dynamicznej aktywności aktywnej/uruchomionej.
Zatrzymane/w tle — działania, które są całkowicie zasłonięte przez inne działanie, są uznawane za zatrzymane lub w tle. Zatrzymane działania nadal próbują zachować informacje o stanie i członkach tak długo, jak to możliwe, ale zatrzymane działania są uważane za najniższy priorytet trzech stanów, a w związku z tym system operacyjny najpierw usunie działania w tym stanie, aby spełnić wymagania dotyczące zasobów działań o wyższym priorytecie.
Ponownie uruchomione — istnieje możliwość, że działanie, na każdym etapie od wstrzymania do zatrzymania w cyklu życia, zostanie usunięte z pamięci przez system Android. Jeśli użytkownik przejdzie z powrotem do aktywności, musi zostać ona ponownie uruchomiona, przywrócona do wcześniej zapisanego stanu, a następnie wyświetlona użytkownikowi.
Działanie Re-Creation w odpowiedzi na zmiany konfiguracji
Aby uczynić sprawy bardziej skomplikowanymi, Android wprowadza kolejny problem zwany Zmiany konfiguracji. Zmiany konfiguracji to szybkie cykle niszczenia i ponownego tworzenia aktywności, które występują w przypadku zmiany konfiguracji aktywności, na przykład gdy urządzenie jest obracane (i aktywność musi być ponownie zbudowana w trybie poziomym lub pionowym), gdy jest wyświetlana klawiatura (a aktywność może się dostosować do zmiany rozmiaru) lub gdy urządzenie jest umieszczone w doku, między innymi.
Zmiany konfiguracji nadal powodują te same zmiany stanu działania, które wystąpią podczas zatrzymywania i ponownego uruchamiania działania. Jednak aby upewnić się, że aplikacja jest responsywna i dobrze się sprawdza podczas zmian konfiguracji, ważne jest, aby te zmiany były obsługiwane tak szybko, jak to możliwe. W związku z tym system Android ma określony interfejs API, który może służyć do utrwalania stanu podczas zmian konfiguracji. Omówimy to w dalszej części sekcji Zarządzanie stanem w całym cyklu życia .
Metody cyklu życia działania
Zestaw SDK systemu Android i platforma Xamarin.Android udostępniają zaawansowany model zarządzania stanem aktywności w aplikacji. Gdy stan działania ulega zmianie, działanie jest powiadamiane przez system operacyjny, który wywołuje określone metody tego działania. Na poniższym diagramie przedstawiono te metody w odniesieniu do cyklu życia działania:
Jako deweloper możesz obsługiwać zmiany stanu, przesłaniając te metody w obrębie aktywności. Należy jednak pamiętać, że wszystkie metody cyklu życia są wywoływane w wątku interfejsu użytkownika i uniemożliwi systemowi operacyjnemu wykonywanie kolejnego fragmentu pracy interfejsu użytkownika, na przykład ukrywanie bieżącego działania, wyświetlanie nowego działania itp. W związku z tym kod w tych metodach powinien być tak krótki, jak to możliwe, aby aplikacja czuła się dobrze. Wszystkie długotrwałe zadania powinny być wykonywane w tle.
Przyjrzyjmy się każdej z tych metod cyklu życia i ich użyciu:
Przytworzenie
OnCreate to pierwsza metoda wywoływana podczas tworzenia działania.
OnCreate jest zawsze nadpisywany, aby wykonać wszystkie inicjalizacje uruchamiania, które mogą być wymagane przez aktywność, takie jak:
- Tworzenie widoków
- Inicjowanie zmiennych
- Wiązanie danych statycznych z listami
OnCreate Przyjmuje parametr Bundle , który jest słownikiem do przechowywania i przekazywania informacji o stanie i obiektów między działaniami Jeśli pakiet nie ma wartości null, oznacza to, że działanie jest uruchamiane ponownie i powinno przywrócić jego stan z poprzedniego wystąpienia. Poniższy kod ilustruje sposób pobierania wartości z pakietu:
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);
}
Po OnCreate zakończeniu system Android wywoła metodę OnStart.
OnStart
OnStart jest zawsze wywoływany przez system po ukończeniu OnCreate. Działania mogą przesłonić tę metodę, jeśli muszą wykonać określone zadania bezpośrednio, zanim działanie stanie się widoczne, takie jak odświeżanie bieżących wartości widoków w ramach działania. Android wywoła OnResume natychmiast po tej metodzie.
OnResume
System wywołuje metodę OnResume , gdy działanie jest gotowe do rozpoczęcia interakcji z użytkownikiem. Działania powinny zastąpić tę metodę, aby wykonywać zadania, takie jak:
- Zwiększenie szybkości klatek na sekundę (typowe zadanie w tworzeniu gier)
- Uruchamianie animacji
- Nasłuchiwanie aktualizacji GPS
- Wyświetlanie dowolnych odpowiednich alertów lub okien dialogowych
- Podłączać zewnętrzne programy obsługi zdarzeń
Na przykład poniższy fragment kodu pokazuje, jak zainicjować aparat:
protected override void OnResume()
{
base.OnResume(); // Always call the superclass first.
if (_camera==null)
{
// Do camera initializations here
}
}
OnResume jest ważne, ponieważ każda operacja wykonywana w OnPause powinna zostać cofnięta w OnResume, ponieważ jest to jedyna metoda cyklu życia gwarantowana do wykonania po OnPause przywróceniu działania aktywności.
OnPause
OnPause jest wywoływany, gdy system ma umieścić działanie w tle lub gdy działanie stanie się częściowo zasłonięte. Działania powinny zastąpić tę metodę, jeśli zajdzie taka potrzeba:
Zatwierdź niezapisane zmiany w danych trwałych
Niszczenie lub czyszczenie innych obiektów zużywających zasoby
Zmniejsz szybkość klatek i zatrzymaj animacje
Wyrejestruj zewnętrzne programy obsługi zdarzeń lub programy obsługi powiadomień (tj. te, które są powiązane z usługą). Należy to zrobić, aby zapobiec wyciekom pamięci Activity.
Podobnie, jeśli działanie wyświetliło jakiekolwiek okna dialogowe lub alerty, należy je wyczyścić za pomocą
.Dismiss()metody .
Na przykład poniższy fragment kodu zwolni aparat, ponieważ Activity nie może z niego korzystać podczas wstrzymania.
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;
}
}
Istnieją dwie możliwe metody cyklu życia, które będą wywoływane po OnPause.
-
OnResumezostanie wywołana, jeśli aktywność ma zostać przywrócona na pierwszy plan. -
OnStopzostanie wywołana, jeśli działanie jest umieszczane w tle.
OnStop
Funkcja OnStop jest wywoływana, gdy działanie nie jest już widoczne dla użytkownika. Dzieje się tak, gdy wystąpi jeden z następujących:
- Rozpoczyna się nowe działanie, które zasłania to działanie.
- Istniejąca aktywność jest przywracana na pierwszy plan.
- Działanie jest niszczone.
OnStop Może nie zawsze być wywoływana w sytuacjach niskiej pamięci, takich jak gdy system Android cierpi na niedobór zasobów i nie może prawidłowo uruchomić Aktywności w tle. Z tego powodu najlepiej nie polegać na wywoływaniu OnStop podczas przygotowywania aktywności do usunięcia. Następne metody cyklu życia, które mogą być wywoływane po tym, to OnDestroy jeśli Activity jest opuszczane, lub OnRestart jeśli Activity powraca do interakcji z użytkownikiem.
OnDestroy
OnDestroy to ostateczna metoda wywoływana w instancji aktywności, zanim zostanie ona zniszczona i całkowicie usunięta z pamięci. W skrajnych sytuacjach system Android może zakończyć proces aplikacji, który hostuje Activity, co spowoduje, że OnDestroy nie zostanie wywołany. Większość działań nie zaimplementuje tej metody, ponieważ większość metod czyszczenia i zamykania została wykonana w metodach OnPause i OnStop . Metoda OnDestroy jest zazwyczaj nadybywana, aby oczyścić długotrwałe zadania, które mogą powodować wycieki zasobów. Przykładem tego mogą być wątki w tle, które zostały uruchomione w OnCreate.
Po zniszczeniu Activity nie będą wywoływane żadne metody cyklu życia.
OnRestart
Polecenie OnRestart jest wywoływane po zatrzymaniu działania przed jego ponownym uruchomieniem. Dobrym przykładem może być naciśnięcie przycisku Strona główna przez użytkownika podczas działania w aplikacji. W takim przypadku wywoływane są metody OnPause i następnie OnStop, a Activity jest przenoszone do tła, ale nie jest niszczone. Jeśli użytkownik miał następnie przywrócić aplikację przy użyciu menedżera zadań lub podobnej aplikacji, system Android wywoła OnRestart metodę działania.
Nie ma ogólnych wytycznych dotyczących rodzaju logiki, która powinna zostać zaimplementowana w programie OnRestart. Jest to spowodowane tym, że OnStart zawsze jest wywoływana, niezależnie od tego, czy Activity jest tworzone, czy ponownie uruchamiane, więc wszelkie zasoby wymagane przez Activity powinny być inicjowane w OnStart, a nie w OnRestart.
Następną metodą cyklu życia o nazwie after OnRestart będzie OnStart.
Powrót a strona główna
Wiele urządzeń z systemem Android ma dwa odrębne przyciski: przycisk "Wstecz" i przycisk "Strona główna". Przykład tego można zobaczyć na poniższym zrzucie ekranu systemu Android 4.0.3:
Istnieje subtelna różnica między dwoma przyciskami, mimo że wydają się mieć taki sam wpływ na umieszczenie aplikacji w tle. Gdy użytkownik kliknie przycisk Wstecz, informuje system Android, że wykonuje działanie. System Android zniszczy aktywność. Natomiast gdy użytkownik kliknie przycisk Strona główna, działanie zostanie umieszczone tylko w tle — system Android nie zabije działania.
Zarządzanie stanem w całym cyklu życia
Gdy aktywność zostanie zatrzymana lub zniszczona, system ma możliwość zapisania jej stanu na potrzeby późniejszego przywracania. Ten zapisany stan jest określany jako stan wystąpienia. System Android udostępnia trzy opcje przechowywania stanu wystąpienia podczas cyklu życia działania:
Przechowywanie wartości pierwotnych w
Dictionaryznanym jako Pakiet, którego system Android użyje do zapisania stanu.Tworzenie niestandardowej klasy, która będzie przechowywać złożone wartości, takie jak mapy bitowe. System Android użyje tej klasy niestandardowej do zapisania stanu.
Obejście cyklu życia zmiany konfiguracji systemu i przyjęcie pełnej odpowiedzialności za utrzymanie stanu w aktywności.
W tym przewodniku omówiono dwie pierwsze opcje.
Stan pakietu
Podstawową opcją zapisywania stanu wystąpienia jest użycie obiektu słownika klucz/wartość nazywanego Bundle.
Pamiętaj, że gdy metoda OnCreate jest wywoływana po utworzeniu aktywności, do niej jest przekazywany Bundle jako parametr; ten Bundle może służyć do przywrócenia stanu instancji. Nie zaleca się używania pakietu do bardziej złożonych danych, które nie będą szybko ani łatwo serializować par klucz/wartość (takich jak mapy bitowe); zamiast tego należy go używać dla prostych wartości, takich jak ciągi.
Aktywność udostępnia metody ułatwiające zapisywanie i pobieranie stanu wystąpienia w Bundle.
OnSaveInstanceState — jest to wywoływane przez system Android, gdy działanie jest niszczone. Działania mogą implementować tę metodę, jeśli muszą utrwalić wszystkie elementy stanu klucz/wartość.
OnRestoreInstanceState — jest to wywoływane po zakończeniu
OnCreatemetody i zapewnia inną możliwość przywrócenia stanu działania po zakończeniu inicjowania.
Na poniższym diagramie przedstawiono sposób użycia tych metod:
OnSaveInstanceState
OnSaveInstanceState zostanie wywołane, gdy Aktywność jest zatrzymywana. Otrzyma parametr pakietu, w ramach którego działanie może przechowywać jego stan. Gdy urządzenie doświadcza zmiany konfiguracji, Activity może użyć przekazanego obiektu Bundle, aby zachować swój stan, nadpisując OnSaveInstanceState. Rozważmy na przykład następujący kod:
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();
};
}
Powyższy kod zwiększa wartość liczby całkowitej o nazwie c po kliknięciu przycisku o nazwie incrementCounter, wyświetlając wynik w TextView o nazwie output. Gdy wystąpi zmiana konfiguracji — na przykład po obróceniu urządzenia — powyższy kod utraci wartość c ponieważ bundle będzie wartością null, jak pokazano na poniższej ilustracji:
Aby zachować wartość c w tym przykładzie, Aktivność może nadpisać OnSaveInstanceState, zapisując wartość w pakiecie, jak poniżej.
protected override void OnSaveInstanceState (Bundle outState)
{
outState.PutInt ("counter", c);
base.OnSaveInstanceState (outState);
}
Teraz, gdy urządzenie jest obrócone do nowej orientacji, liczba całkowita jest zapisywana w pakiecie i pobierana za pomocą linii:
c = bundle.GetInt ("counter", -1);
Uwaga / Notatka
Ważne jest, aby zawsze wywoływać podstawową implementację OnSaveInstanceState, dzięki czemu stan hierarchii widoków także zostanie zapisany.
Stan widoku
Zastępowanie OnSaveInstanceState jest odpowiednim mechanizmem zapisywania danych przejściowych w aktywności w trakcie zmian orientacji, tak jak licznik w powyższym przykładzie. Jednak domyślna implementacja OnSaveInstanceState programu zajmie się zapisywaniem danych przejściowych w interfejsie użytkownika dla każdego widoku, tak długo, jak każdy widok ma przypisany identyfikator. Załóżmy na przykład, że aplikacja ma EditText element zdefiniowany w formacie XML w następujący sposób:
<EditText android:id="@+id/myText"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
Ponieważ kontrolka EditText ma przypisaną id wartość, gdy użytkownik wprowadza pewne dane i obraca urządzenie, dane są nadal wyświetlane, jak pokazano poniżej:
OnRestoreInstanceState
OnRestoreInstanceState zostanie wywołana po OnStart. Zapewnia działaniu możliwość przywrócenia dowolnego stanu, który został wcześniej zapisany w Bundlu podczas poprzedniego OnSaveInstanceState. Jest to ten sam pakiet, który jest dostarczany do OnCreate.
Poniższy kod pokazuje, jak można przywrócić stan w programie OnRestoreInstanceState:
protected override void OnRestoreInstanceState(Bundle savedState)
{
base.OnRestoreInstanceState(savedState);
var myString = savedState.GetString("myString");
var myBool = savedState.GetBoolean("myBool");
}
Ta metoda istnieje, aby zapewnić pewną elastyczność w przypadku przywrócenia stanu. Czasami bardziej odpowiednie jest poczekanie na ukończenie wszystkich inicjalizacji przed przywróceniem stanu wystąpienia. Ponadto podklasa istniejącego działania może chcieć przywrócić tylko niektóre wartości ze stanu wystąpienia. W wielu przypadkach nie jest konieczne zastąpienie OnRestoreInstanceState, ponieważ większość aktywności może przywrócić stan, korzystając z dostarczonego pakietu dla OnCreate.
Aby zapoznać się z przykładem zapisywania stanu przy użyciu elementu Bundle, zapoznaj się z przewodnikiem — zapisywanie stanu działania.
Ograniczenia pakietu
Chociaż OnSaveInstanceState ułatwia zapisywanie danych przejściowych, ma pewne ograniczenia:
Nie jest wywoływana we wszystkich sytuacjach. Na przykład naciśnięcie przycisku Strona główna lub Powrót w celu zakończenia działania nie spowoduje
OnSaveInstanceStatewywołania.Pakiet przekazany do
OnSaveInstanceStatenie jest przeznaczony dla dużych obiektów, takich jak obrazy. W przypadku dużych obiektów preferowane jest zapisanie obiektu z onRetainNonConfigurationInstance , jak opisano poniżej.Dane zapisane przy użyciu pakietu są serializowane, co może prowadzić do opóźnień.
Stan pakietu jest przydatny w przypadku prostych danych, które nie zajmują dużo pamięci, natomiast dane wystąpienia niekonfiguracyjne są przydatne w przypadku bardziej złożonych danych lub danych, których pobranie jest kosztowne, na przykład z wywołania usługi internetowej lub skomplikowanego zapytania bazy danych. Dane wystąpienia, które nie są związane z konfiguracją, są zapisywane w obiekcie w miarę potrzeb. W następnej sekcji przedstawiono OnRetainNonConfigurationInstance sposób zachowania bardziej złożonych typów danych za pomocą zmian konfiguracji.
Przechowywanie złożonych danych
Oprócz utrwalania danych w pakiecie system Android obsługuje również zapisywanie danych przez zastąpienie klasy OnRetainNonConfigurationInstance i zwrócenie wystąpienia elementu zawierającego Java.Lang.Object dane do utrwalania. Istnieją dwie podstawowe korzyści wynikające z używania OnRetainNonConfigurationInstance funkcji do zapisywania stanu:
Obiekt zwracany z
OnRetainNonConfigurationInstancedziała dobrze z większymi, bardziej złożonymi typami danych, ponieważ pamięć zachowuje ten obiekt.Metoda jest wywoływana
OnRetainNonConfigurationInstancena żądanie i tylko wtedy, gdy jest to konieczne. Jest to bardziej ekonomiczne niż korzystanie z ręcznej pamięci podręcznej.
Użycie OnRetainNonConfigurationInstance jest odpowiednie w scenariuszach, w których pobieranie danych jest kosztowne wielokrotnie, na przykład w wywołaniach usługi internetowej. Rozważmy na przykład następujący kod, który wyszukuje w serwisie Twitter:
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);
}
}
Ten kod pobiera wyniki z sieci Web sformatowanej jako JSON, analizuje je, a następnie przedstawia wyniki na liście, jak pokazano na poniższym zrzucie ekranu:
Gdy wystąpi zmiana konfiguracji — na przykład po obróceniu urządzenia — kod powtarza proces. Aby ponownie użyć pierwotnie pobranych wyników i nie powodować niepotrzebnych, nadmiarowych wywołań sieciowych, możemy użyć OnRetainNonconfigurationInstance polecenia , aby zapisać wyniki, jak pokazano poniżej:
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};
}
}
Teraz gdy urządzenie zostanie obrócone, oryginalne wyniki są pobierane z właściwości LastNonConfiguartionInstance. W tym przykładzie wyniki składają się z string[] zawierających tweety. Ponieważ OnRetainNonConfigurationInstance wymaga zwrócenia Java.Lang.Object, string[] jest opakowany w klasę, która jest podklasą Java.Lang.Object, jak pokazano poniżej:
class TweetListWrapper : Java.Lang.Object
{
public string[] Tweets { get; set; }
}
Na przykład próba użycia TextView jako obiektu zwracanego przez OnRetainNonConfigurationInstance spowoduje wyciek Aktywności, jak pokazano w poniższym kodzie:
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;
}
W tej sekcji nauczyliśmy się, jak zachowywać proste dane o stanie za pomocą Bundle, i utrwalać bardziej złożone typy danych za pomocą OnRetainNonConfigurationInstance.
Podsumowanie
Cykl życia działania systemu Android zapewnia zaawansowaną strukturę zarządzania stanami działań w aplikacji, ale może to być trudne do zrozumienia i zaimplementowania. W tym rozdziale przedstawiono różne stany, przez które działanie może przechodzić w okresie jego istnienia, a także metody cyklu życia skojarzone z tymi stanami. Następnie podano wskazówki dotyczące rodzaju logiki, jaką należy wykonać w każdej z tych metod.