Cykl życia obiektu statycznego systemu Android

101

Tworzę aplikację do wyszukiwania zdarzeń, ustawiamy kryteria wyszukiwania z jednego ekranu wypełniającego na innym ekranie, a następnie użytkownik może edytować kryteria wyszukiwania z trzeciego ekranu i przechodzi do czwartego ekranu.

Aby wykonać powyższe zadanie, używam statycznego obiektu, który zapamiętuje wartości wokół aplikacji i nie muszę robić nic więcej.

Ale obawiam się, że jeśli chodzi o cykl życia obiektów statycznych w systemie Android, jeśli wykryto małą ilość pamięci, Android usunąć obiekty statyczne?

Ponieważ Android obsługuje wielozadaniowość, jeśli użytkownik przełączy się na inną aplikację i gdy użytkownik wróci, aplikacja zacznie działać szalenie, czy statyczny obiekt zostanie usunięty, gdy będzie działał wielozadaniowo ??? dowolny pomysł ?? a także sugerować trzymanie statycznego obiektu metodą singletona jest lepszym podejściem ???

d-man
źródło

Odpowiedzi:

239

Zacznijmy od odrobiny tła: co się dzieje, gdy uruchamiasz aplikację?
System operacyjny uruchamia proces i przypisuje mu unikalny identyfikator procesu oraz przydziela tabelę procesów. Proces uruchamia instancję programu DVM (Dalvik VM); Każda aplikacja działa w DVM.
DVM zarządza rozładowywaniem klas ładowania, cyklem życia instancji, GC itp.

Okres istnienia zmiennej statycznej: zmienna statyczna powstaje, gdy klasa jest ładowana przez maszynę JVM i umiera, gdy klasa jest wyładowywana.

Jeśli więc utworzysz aplikację dla systemu Android i zainicjujesz zmienną statyczną, pozostanie ona w JVM do czasu, gdy nastąpi jedno z poniższych:
1. klasa zostanie wyładowana
2. maszyna JVM zostanie zamknięta
3. proces umiera

Zwróć uwagę, że wartość zmiennej statycznej będzie trwała, gdy przełączysz się na inną aktywność innej aplikacji i nie nastąpi żadne z powyższych trzech. W przypadku wystąpienia któregokolwiek z powyższych trzech statyczna straci swoją wartość.

Możesz to sprawdzić za pomocą kilku linijek kodu:

  1. wypisuje niezainicjalizowane statyczne w onCreate twojej aktywności -> powinno wypisać null
  2. zainicjuj plik static. wydrukuj to -> wartość będzie różna od null
  3. Naciśnij przycisk Wstecz i przejdź do ekranu głównego. Uwaga: Ekran główny to kolejna czynność.
  4. Uruchom ponownie swoją aktywność -> zmienna statyczna będzie różna od null
  5. Zabij proces aplikacji z DDMS (przycisk zatrzymania w oknie urządzeń).
  6. Zrestartuj swoją aktywność -> statyczny będzie miał wartość null.

Mam nadzieję, że to pomoże.

Samuh
źródło
1
Chcę wiedzieć, dlaczego tracę wartość pola w obiekcie aplikacji, jeśli nie jest ona statyczna, gdy rozpoczynam nową aktywność, na przykład deklaruję zmienną bieżącą stronę w obiekcie aplikacji, a jej wartość zawsze wraca do zera, gdy otwieram nową aktywność
Mohammed Subhi Sheikh Quroush
kiedy dzwonię do super.onRestoreInstanceState (saveInstanceState); Tracę zmienne, nawet jeśli są statyczne, na czym polega problem?
Mohammed Subhi Sheikh Quroush
1
to fajne wyjaśnienie (więc nie -1), ale jest trochę nieistotne: OP zapytał wyraźnie o „sytuacje małej ilości pamięci” (ten sam powód, dla którego tu jestem), gdzie, o ile wiem, system operacyjny może zabić maszynę wirtualną i zrestartuj go później z tymi samymi parametrami, a ten przypadek ( JEŚLI to jest prawdziwy) nie jest tutaj omówiony ...
Rick77
1
@suitianshi Myślę, że możemy zainicjować instancje statyczne w Application.onCreate, ponieważ nawet jeśli nasza aplikacja przejdzie w tło i proces zostanie zabity, jak tylko wrócimy do naszej aplikacji, klasa Application zostanie utworzona i wywoła odpowiednie metody cyklu życia jeszcze raz! chociaż potrzebuję potwierdzenia tego, zastanawiam się, czy może istnieć scenariusz, w którym wystąpienie statyczne zainicjowane w Application.onCreate traci swoją wartość?
Sarthak Mittal
1
Brakuje mi tutaj wyjaśnienia „1. klasa jest rozładowana” - kiedy to się stanie? Czy JVM wyładuje klasę, jeśli zaczyna brakować pamięci?
stoefln
16

Cóż, wzorzec Singleton jest również oparty na użyciu zmiennych statycznych, więc w rzeczywistości byłbyś w tej samej pozycji. Chociaż podejście statyczne może działać w większości przypadków, może się zdarzyć, że w niektórych przypadkach, gdy pamięć jest pełna, a inne działanie zajmuje pierwszy plan, zanim aplikacja przejdzie do następnego ekranu, proces działania może zostać przerwany i utracisz wartości statyczne. Jednak Android oferuje kilka opcji utrwalania wartości między stanami lub przesyłania ich, takich jak:

  • korzystając z zamiaru, możesz przekazywać kryteria wyszukiwania z czynności do czynności (podobnie jak w przypadku żądania http w sieci WWW)
  • Korzystając z preferencji aplikacji, można zapisać wartości i odzyskać je w działaniu, które ich wymaga
  • Używając bazy danych sqlite, możesz zachować je w tabeli i odzyskać później
  • jeśli potrzebujesz tylko zapisać stan aktywności, aby po restarcie pola zostały wypełnione ich wcześniej wybranymi wartościami, możesz zaimplementować metodę aktywności onSaveInstanceState () - pamiętaj, że nie jest to zalecane dla trwałości stanów między działaniami.

Możesz uzyskać kilka przykładów kodu wykorzystania preferencji, intencji i bazy danych sqlite, patrząc na drzewo kodu źródłowego Aegis-Shield w kodzie Google lub w innych aplikacjach na Androida typu open source.

r1k0
źródło
6

Po kilku badaniach okazuje się, że wykorzystanie aplikacji do przechowywania singletonów nie jest takim świetnym pomysłem, chyba że jesteś gotowy, aby go odtworzyć:

Nie przechowuj danych w obiekcie aplikacji

więc chociaż zaakceptowana odpowiedź jest poprawna technicznie, nie zawiera wszystkich informacji.

Jak sugeruje powyższy link, jeśli naprawdę chcesz trzymać się tego modelu, musisz być gotowy na sprawdzenie wartości null i odtworzenie danych, jeśli to możliwe.

Rick77
źródło
3

@ r1k0 jest tutaj. Przechowywanie danych w statycznych polach klasy nie będzie trwać samoistnie podczas kończenia i ponownego uruchamiania procesów aplikacji. Android rutynowo zabija procesy (uruchomione aplikacje), gdy potrzebuje pamięci.

Zgodnie z dokumentem systemu Android: stan aktywności i wyrzucenie z pamięci ,

System nigdy bezpośrednio nie zabija aktywności. Zamiast tego zabija proces, w którym działa działanie, niszcząc nie tylko działanie, ale także wszystko inne działające w tym procesie.

Możesz zapisywać i przywracać stan prymitywów, a także obiektów serializowalnych i parcelowalnych, korzystając z poniższych metod. Są one wywoływane automatycznie podczas normalnego cyklu życia czynności.

protected void onSaveInstanceState(Bundle state) {}
protected void onRestoreInstanceState(Bundle savedInstanceState){}

Tak więc, jeśli masz klasę, która ma tylko zmienne statyczne, możesz zapisać stan każdego pola w onSaveInstanceState () i przywrócić je w onRestoreInstanceState (). Gdy Android zabije proces, w którym działa Twoja aplikacja, stan twoich zmiennych zostanie zapisany, a gdy Android przywróci aplikację, wartości zostaną przywrócone w pamięci w takim samym stanie jak poprzednio.

eric.mcgregor
źródło