2016-07-26 31 views
6

Mam Fragment, który ma RecyclerView.Pamięć nie zwalniająca po usunięciu fragmentu

W tym RecyclerView, może od czasu do czasu pobierania i wyświetlania obrazów (ładowany z Glide do ImageView.

Więc kiedy otworzyć Fragment stosowane pamięci może czasami skoczyć z około 30MB do około 100 MB lub nawet więcej.

Po Activity która trzyma Fragment zakończeniu pamięć nie zwolnić. To pozostaje taka sama jak poprzednio.

Glide sprawdziłem dokumentację i widocznie nie musimy się martwić o uwolnienie Bitmaps w RecyclerView. Jest to poważny problem, ponieważ aplikacja często zawiesza się z powodu OOM z tego powodu.

Jak poprawnie obsługiwać zwalnianie pamięci po usunięciu Fragment?

Edit: Kolejna obserwacja

Inną rzeczą, jaką zauważyłem jest to, że jeśli skończę Activity a następnie ponownie uruchomić tę samą Activity. Pamięć zeskoczy z powrotem na chwilę, a następnie z powrotem do 100 MB, co prowadzi mnie do przekonania, że ​​pamięć została wyczyszczona przed ponownym uruchomieniem Fragment.

Odpowiedz

4

Usuwanie śmieci jest czasami bolesnym problemem w systemie Android. Większość programistów nie bierze pod uwagę tego problemu i rozwija się dalej bez żadnego przydziału zasobów.

Spowoduje to oczywiście problemy z pamięcią, takie jak wycieki, OOM i niepotrzebne wiązanie zasobów. Nie ma absolutnie żadnego automatycznego sposobu zwolnienia pamięci. Państwo nie może w żadnym wypadku polegać wyłącznie na śmieciarza

Kiedykolwiek przekazać Fragment użytkownika lub aktywny na onDestroy() metoda, co można i należy zrobić, to usunąć dowolną konstrukcję, że nie będą już wymagane w aplikacji. Możesz wykonać następujące czynności:

  1. Unikaj anonimowych wystąpień słuchaczy. Twórz słuchaczy i niszcz ich, gdy już ich nie potrzebujesz.
  2. Ustaw wszystkie detektory (tak je kliknij, długie kliknięcie, itp.) Na wartość null
  3. Wyczyść wszystkie zmienne, tablice. Zastosuj tę samą procedurę do wszystkich klas i podklas zawartych wewnątrz Aktywny/Fragment
  4. Ustaw zmienną null dowolnym momencie wykonać dowolną z poprzednich etapów na tej danej klasy (dotyczy wszystkich zmiennych)

Co ja zakończyła się robi było stworzenie interfejsu podobnego

public interface clearMemory(){ 
    void clearMemory(); 
} 

i wdrożenie go w każdej klasie, czy to aktywny, fragment lub normalna klasa (zawiera adaptery, niestandardowe widoki, itp.)

ja następnie wywołać zawsze, gdy klasa ma być zniszczone (ponieważ aplikacja był zniszczony lub gdy tylko odczuwana potrzeba, aby to zrobić. Ostrożnie nie wyrzucać normalnego wykonania)

@Override 
public void onDestroy(){ 
    clearMemory(); 
} 

public void clearMemory(){ 
    normalButtonOnClickListener = null; 
    normalButton.setOnClickListener(null); 
    normalButton = null; 
    myCustomClass.clearMemory(); // apply the interface to the class and clear it inside 
    myCustomClass = null; 
    simpleVariable = null; 
    ...   
} 

Realizując to w sposób systematyczny zarządzanie pamięcią w aplikacjach stało się łatwiejsze i szczuplejsze. Następnie można dokładnie poznać/kontrolować, jak i kiedy pamięć jest usuwana.

+0

Dzięki, to zdecydowanie pomaga. Dam to jutro spróbować (chociaż może to potrwać jakiś czas, zanim zrobię to w całej aplikacji), a dam ci znać, jak poszło. – Guy

+0

Kiedy powiedziałeś, że chcesz wyczyścić wszystkie zmienne, oznacza to zmienne instancji, prawda? Jeśli utworzę zmienną w metodzie onCreate, czy powinienem wyczyścić tę zmienną po jej zaprzestaniu? – Guy

+0

Tak. Wszystko, co przyznajesz, musi/powinno być załatwiane, gdy tylko wiesz, że nie będziesz już tego potrzebować. Jako metafora: 1) Kupujesz kawałek jednorazowego papieru. Na tej kartce piszesz kilka faktów o swoim dniu 2) Użyjesz tego kawałka papieru przez cały dzień, ale wiesz, że nie będziesz potrzebował papieru na zawsze 3) Pod koniec dnia zdajesz sobie sprawę, że papier teraz spełnił swój cel. 4) Papier należy wyrzucić, rozrywając go i wyrzucając do kosza na śmieci. Rozumiem teraz "kartkę papieru" jako dowolną zmienną, której używasz, i swój "dzień" jako cykl życia aktywności. –

1

To dodaje do odpowiedzi Ricardo.

Możesz dodać następujący kod do rozpoczęcia zbierania śmieci w Androidzie:
Runtime.getRuntime().gc();

Uwaga: wywołać tę funkcję po dokonaniu wszystkie zmienne lokalne zerowa. Wykonanie tego kodu nie gwarantuje, że system będzie zbierał śmieci w Twojej aplikacji, jedynie wskazuje, że może to być dobry moment, aby to zrobić.
Użyłem tego we wszystkich moich działaniach "onDestroy(), i zawsze wydaje się działać, gdy chcę tego.
Spróbuj, może ci pomóc.

+0

Dokładnie. Można zasadniczo wywołać System.gc(), aby "podpowiedzieć" system, i ostatecznie zostanie wykonany, aby zebrać wszystkie obiekty bez odniesień. Kontrolowane zarządzanie pamięcią jest zawsze istotną częścią każdej aplikacji! –