2012-01-26 19 views
5

SETUP:Pamięci i Działania :: OutOfMemory

mam to aplikacja, która ma 4 działalność na torze liniowym, naprawdę prosta nawigacja: A -> B -> C -> D

Wszystko czynności mają ten sam obraz tła, a wszystkie mają kilka zwykłych przycisków, widok tekstowy lub editekst. Wszystkie są zdefiniowane w osobnych plikach xml widoku.

Tło jest gradientem i jest dość ciężkie. Około 3 MB jako nieskompresowana bitmapa.

Aplikacja ma jeszcze nic, tylko logika w tym, to na rozpoczęcie działalności i zamykając je na przycisk kliknie

Próbowałem użyć MAT znaleźć przeciek pamięci, ale nie mógł znaleźć niczego. Największy zachowany rozmiar w mojej aplikacji wynosi 656 (ko?), A całkowity zachowany rozmiar dla aplikacji to 1520 (ko?) I nie mogę znaleźć żadnego obiektu, który mógłby zostać zduplikowany. który na drodze całkowicie sprzeczne dumpsys który pokazuje 27300 (? Ko) przeznaczono

problemy:

  1. Kiedy nawigacja UP, widzę wzrost o równowartość zużycia pamięci do rozmiaru tła.
  2. Gdy nawiguję w DÓŁ, ​​zamykając czynności za pomocą przycisku Wstecz lub polecenia Zakończ, zużycie pamięci przez aplikację nie spada.
  3. Jeśli przejdę z A do D, a następnie z powrotem do B i obrócę ekran, siła aplikacji zostanie zamknięta z wyjątkiem OutOfMemory Exception.

PYTANIA:

Aktualizacja: Myślę, że prawdziwe pytanie brzmi: dlaczego mam ogromny wyciek pamięci (5 mega na raz) o wielkości 27megs aplikacji w czasie zamrożenia i nie mogę zobacz to w MAT?

  1. Dlaczego system Android miałby rozpakować wiele razy to samo tło, raz na aktywność? Wydaje się nieskuteczne.
  2. Czy można przezwyciężyć ten problem za pomocą motywów, czy też zobaczę to samo "przydzielić 1 tło według aktywności"?
  3. Dlaczego działania nie są odzyskiwane po zamknięciu?
  4. Dlaczego MAT i dumpsys prezentują różne liczby?

CLUES

dokładnie w tym samym czasie mam: dumpsys meminfo:

Applications Memory Usage (kB): 
Uptime: 74006853 Realtime: 110962243 

** MEMINFO in pid 22683 [com.kayenko.sosadresse] ** 
        native dalvik other total 
      size: 20820  5767  N/A 26587 
     allocated: 18751  2901  N/A 21652 
      free:  312  2866  N/A  3178 
      (Pss):  1357  201 16782 18340 
    (shared dirty):  2264  1804  5456  9524 
    (priv dirty):  1280  116 16032 17428 

Objects 
      Views:  0  ViewRoots:  0 
    AppContexts:  0  Activities:  0 
      Assets:  2 AssetManagers:  2 
    Local Binders:  18 Proxy Binders:  16 
Death Recipients:  1 
OpenSSL Sockets:  0 

SQL 
       heap:  0   MEMORY_USED:  0 
PAGECACHE_OVERFLOW:  0   MALLOC_SIZE:  0 

A to drzewo dominator:

MAT Dominator tree

Thansk każdemu z wskazówka, kim jestem przypuszczam, aby szukać.

Odpowiedz

7

Pamięć to bardzo trudny temat w systemie Android.

Każda aplikacja pobiera limit pamięci sterty w zależności od urządzenia. Ta pamięć sterty jest pamięcią dalvik plus pamięcią rodzimą i można ją zobaczyć jako całkowitą kolumnę wyników dumpsys meminfo. Pamięć dalvik zajmuje się wszystkim oprócz bitmap, które są przydzielane w pamięci rodzimej (dotyczy to wersji Androida przed Honeycomb).

Mimo, że mogę odpowiedzieć tylko na niektóre pytania:

  1. O ile mi wiadomo, Android zawsze będzie przydzielić pamięci dla bitmap, nawet jeśli są one takie same. Dlatego w twoim przypadku każda aktywność przydziela pamięć dla twojego tła.

  2. Nie wiem, czy lepiej pracować z motywami, musisz spróbować.

  3. Z jednej strony działania nie są odzyskiwane, gdy urządzenie ma wystarczającą ilość pamięci, aby poradzić sobie z następnym działaniem. Każda czynność jest wypychana na stos, skąd jest odzyskiwana po naciśnięciu przycisku Wstecz. W przypadku, gdy Android potrzebuje więcej pamięci, usuwa jedno działanie ze stosu, który rozdziela jego pamięć (wracając do pytania numer jeden, być może dlatego nie współużytkuje pamięci). Z drugiej strony możesz ustawić działania launchMode, aby zmienić to zachowanie (spójrz na here).

  4. Myślę, że MAT nie pokazuje danych natywnej pamięci. Użyj natywnej kolumny dumpsys meminfo, aby zobaczyć, ile jest przydzielonej pamięci dla bitmap.

Ja sam miałem ciężkie czasy związane z problemami z OutOfMemory. Teraz mam o wiele bardziej przejrzysty pomysł, jak to działa i mogę pracować z dużymi plikami bez wyczerpania pamięci. Gorąco polecam te dwa środki, które bardzo mi pomogło:

Powodzenia!

+0

Dzięki Xavi, było to bardzo pouczające. Widziałem już linki, które mi dałeś, ale nic nie pomogło niestety. Nie wiedziałem o trybie uruchamiania i muszę przyznać, że nie rozumiałem, co ma robić. Chyba będę musiał to przetestować, ponieważ dokumentacja jest jak zwykle "brakująca" :) – Yahel

+1

Zaznaczę twoją odpowiedź jako odpowiedź, ponieważ dałeś mi 3 odpowiedzi z 4: D – Yahel

0

Aby zniszczyć swoją aktywność, należy użyć mapy bitowej jako tło podczas bezpośredniego przetwarzania. Kod będzie tak:

@Override 
protected void onDestroy() { 
    Drawable drawable = getView().getBackground(); 
    if (drawable instanceof BitmapDrawable) { 
     ((BitmapDrawable)drawable).getBitmap().recycle(); 
    } 
    drawable.setCallback(null); 
    getView().setBackgroundDrawable(null); 
    super.onDestroy(); 
} 

Może trzeba zwolnić zasoby rekurencyjnie do zagnieżdżonych widoki, ale to zależy od konstrukcji układu. Jest to ogólny przypadek:

+0

Dzięki za wejście, niestety to wcale nie pomogło. Żaden z moich widgetów nie ma bitmapdrawables zgodnie z kodem, a także wypróbowałem kod z tej strony: http://www.alonsoruibal.com/bitmap-size-exceeds-vm-budget/, a następnie miks z tych dwóch jako agresywny, jak to możliwe, ale bez skutku. – Yahel

+0

Nie zgadzam się. Dalvik będzie automatycznie odtwarzał mapy bitowe, gdy nie będzie już żadnych odniesień do niego. Nie trzeba tego robić ręcznie, istnieje metoda recycle(), więc możesz przyspieszyć ten proces i odzyskać pamięć z góry. –

4

Więc po wielu godzinach badań i pomocy Xavi oto wyniki:

Q. Dlaczego Android dekompresji kilka razy to samo tło, raz na działalność? Wydaje się nieskuteczne.

A. Nawet jeśli wydaje się logiczne, że można poprosić o bitmapę, aby można ją było udostępniać w różnych działaniach, ponieważ jesteśmy na urządzeniach mobilnych z niewielką ilością pamięci, wydaje się, że nie istnieje ona w systemie Android. Za każdym razem, gdy bitmapa jest używana w różnych działaniach, nie jest ona kompresowana do pamięci rodzimej.

P. Czy można rozwiązać ten problem za pomocą motywów, czy też zobaczę to samo "przyporządkowanie jednej bitmapy aktywności"?

Po eksperymentach pamięć zużywana przy użyciu motywów nie różni się wcale od ilości pamięci używanej przez wyraźne ustawienie bitmapy w xml układów. Jest to dla mnie dziwne, ponieważ stylizacja polega na grupowaniu atrybutów w to samo miejsce.

P. Dlaczego czynności nie są regenerowane po zamknięciu?

A. No cóż, nie jestem pewien, ale znalazłem to, że to dało mi błędy OOM prawie tylko podczas debugowania. Podczas uruchamiania aplikacji z urządzenia prawie nigdy się to nie zdarzyło. Błąd w procesie debugowania? Wypróbuj go, zanim stracisz 5 godzin na testowanie rzeczy na milion.

P. Dlaczego MAT i dumpsys prezentują różne liczby?

A. Odpowiedź Xaviego jest poprawna, dumpsys meminfo pokazuje całą przydzieloną pamięć (native + dalvik), podczas gdy MAT pokazuje tylko Dalvik. Ponieważ piksele bitmap są przydzielane w pamięci rodzimej, MAT ich nie zobaczy. Dzieje się tak tylko przed Androidem 3.0, gdzie zmienili schemat alokacji i dopasowali dane pikselowe bitmapy do Dalvik.

Q. Jak mogę rozwiązać mój problem

A. Po pierwsze to nie mogło być problem, gdy nie debugowania. Po drugie, aby być po bezpiecznej stronie Wymieniłem gradient png o kształcie z gradientu radialnego i używane

getWindow().setFormat(PixelFormat.RGBA_8888); 
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DITHER); 

w onCreate moich działań, aby spróbować uniknąć smug. Nadal będę mieć banding na niektórych urządzeniach, ale wolałbym mieć banding niż FCs

Powiązane problemy