2011-07-29 12 views
8

Myślę, że jest to pytanie zadawane wcześniej, ale wciąż są rzeczy, których nie mogę zrozumieć.Buforowanie obrazu w systemie Android - jak?

Próbowałem dwa różne podejścia:

  1. przechowywać wszystkie obrazy z pamięci, gdy pewna graniczna zaczęła przekraczać rozpocząć usuwanie ich
  2. Niech Android rozwiązać ten z SoftReferences

W 2. jest to po prostu czyszczenie ich, czasami, gdy je przydzielam! I nie przypisuję zbyt wiele - 30-40 obrazów 50x50 pikseli.

Więc trzymam się jednego. Pytanie brzmi, jaki jest limit?

  1. Czy mogę uzyskać wiarygodne informacje z urządzenia o tym, ile dokładnie pamięci bitowej mam? Zrobiłem kilka badań, obserwowałem wartości DDMS, to po prostu zajmuje coraz więcej miejsca (jeśli nie sprzątam), dopóki nie eksploduje. W tej chwili pozostało tylko 200 KB, następnie system zapewnia 2M więcej ...
  2. Obecnie używam decyzji heurystycznej, w oparciu o model urządzenia lub rozmiar ekranu. Myślę, że jest to ślepa uliczka na dłuższą metę. Mam wyjątki pamięci na niektórych telefonach, całkowicie za darmo na innych.
  3. Czy istnieje trzecie rozwiązanie, właściwe?
+0

30-40 obrazów o wielkości 50x50 nie powinno powodować NIEKTÓRYCH. Być może ładujesz większe? Jeśli tak, możesz je zmniejszyć. Ponadto, jeśli niektóre obrazy zostaną wyczyszczone z SoftReference, nie są używane, więc po prostu je wczytaj ponownie, jeśli to konieczne. –

Odpowiedz

8

najważniejsze pytanie: Czy czy twoje mapy bitowe? Jest to bardzo ważne w przypadku aplikacji poprzedzających pierniki (może również po Gingerbread).

Oglądanie Memory Management for Android Apps session from Google I/O 2011 pomogło mi lepiej zrozumieć specyfikę programowania dla Androida.

W tym wideo wymieniono narzędzie o nazwie MAT - a Memory Analyzer - które jest przydatne do określania, czy obiekty wisi w pamięci, które wyciekły. Prawdopodobnie masz więcej niż 30-40, które myślisz, że masz.

Do przeglądania i/lub rejestrowania bieżącego rozmiaru sterty itd., Sugeruję użycie kodu w this answer about Android Out of Memory exceptions.

+0

Dziękuję za link. Próbowałem je odtworzyć, ale są one używane w niektórych widokach, a to powoduje awarie, gdy wracam do działania, w którym są używane. – Danail

2

Granica jest związane z wielkością sterty VM na urządzenie to działa w, ponieważ różni się od urządzenia, urządzenia i OS Os może mieścić się w zakresie od 16 MB (łącznie dla APP) do 256 + (w tabletkach).

Musisz albo zachować go pod dolnym końcem, tworzyć różne kompilacje na urządzenie, albo sprawdzić aplikację w czasie pracy, co to jest przydział i odpowiednio załadować zdjęcia.

Istnieją metody sprawdzania ilości wolnego miejsca w stercie i to rozmiar:

Ten interfejs API ref pomoże Ci metod Dostepne:

http://developer.android.com/reference/android/app/ActivityManager.html#getMemoryClass

+0

Hmm. Co mam tam użyć? MemoryInfo? Wydaje mi się nieco powściągliwy i czy chodzi o rodzimą kupę? Lub normalna kupa? Użyłem do tej pory Debug.getNativeHeapFreeSize(), ale jest niewiarygodne - daje TYMCZASOWY maksymalny rozmiar limitu, który można zwiększyć, jeśli aplikacja chce więcej pamięci bitmapowej. – Danail

+0

Nie chcesz używać informacji o rodzimych stertach, chyba że jawnie alokujesz je za pomocą NDK. Maszyna wirtualna Java daje wielkość sterty, część tej wielkości sterty może być przydzielona natywnie przez pewne wywołania fabryczne, takie jak te bitmapy. Jest to odejmowane od przydzielonego rozmiaru sterty VM, nawet jeśli jest natywna, więc jeśli stert VM wynosi 16, możesz przydzielić 4MB natywnie, wtedy będziesz miał pozostałe 12 w Sterty VM. getMemoryClass() i getLargeMemoryClass() podadzą stertę VM "class" dozwoloną przez urządzenie, z którego korzystasz. Jest to maksymalna dozwolona przez ciebie aplikacja. – Hamid

0

Z perspektywy wysokiego poziomu ładowanie i zapisywanie obrazów jest częścią GreenDroid framework. Sprawdź to.

4

Buforowanie zdjęć było istotną częścią aplikacji, którą stworzyłem i umieściłem w sklepie z aplikacjami.Aplikacja musi pobierać obrazy i zapisywać je w pamięci podręcznej zarówno w pamięci, jak i na karcie SD, tak aby ich zakres wykraczał poza jednorazowy przebieg.

Ogólna koncepcja polegała na dodaniu obrazów do menedżera buforowania, który zarówno a) przechowuje obraz w pojemniku asocjacyjnym (HashMap), za pomocą klucza na podstawie metadanych, jak i b) zapisuje plik obrazu do pliku SDCard.

W warunkach niskiej ilości pamięci, zwalniam mapę HashMap. Jednak obrazy można nadal pobierać z karty SD_Card i ponownie przechowywać w pamięci podręcznej.

Udało mi się to zrobić bez recyklingu i nadal nie widzę problemów z pamięcią. Jak rozumiem, recykling nie jest konieczny, ale pomaga uzyskać wcześniejsze wydanie pamięci używanej dla "bitmap" z uwagi na to, że przydział dla bitmap, w systemach pre-piernikowych korzysta z Natywnej pamięci. to jest pamięć, która nie jest częścią sterty Dalvik. Tak więc Garbage Collector nie zwalnia tej pamięci, a raczej jest zwalniany przez konkretne zasady implementacji.

To z klasy Cache_Manager:

public static synchronized void addImage(Bitmap b, String urlString, boolean bSaveToFile, IMAGE_TYPES eIT, boolean bForce) 
{ 
    String szKey = getKeyFromUrlString(urlString, eIT); 

    if (false == m_hmCachedImages.containsKey(szKey) || bForce) 
    { 
     m_hmCachedImages.put(szKey, b); 
     if (bSaveToFile) 
     { 
      boolean bIsNull = false; 
      // Write a null object to disk to prevent future query for non-existent image. 
      if (null == b) 
      { 
       try 
       { 
        bIsNull = true; 
        b = getNullArt(); 
       } 
       catch (NullPointerException e) 
       { 
        e.printStackTrace(); 
        throw e; 
       } 
      } 

      // Don't force null art to disk 
      if (false == File_Manager.imageExists(szKey) || (bForce && bIsNull == false)) 
       File_Manager.writeImage(b, szKey); 
     } 
    } 
} 

// Tutaj przykładem writeImage() z klasy File_Manager

public static void writeImage(Bitmap bmp, String szFileName) 
{ 
    checkStorage(); 

    if (false == mExternalStorageWriteable) 
    { 
     Log.e("FileMan", "No Writable External Device Available"); 
     return; 
    } 

    try 
    { 
     // Create dirctory if doesn't exist 
     String szFilePath = getFilesPath(); 
     boolean exists = (new File(szFilePath)).exists(); 
     if (!exists) 
     { 
      new File(szFilePath).mkdirs(); 
     } 

     // Create file 
     File file = new File(szFilePath, szFileName); 

     // Write to file 
     FileOutputStream os = new FileOutputStream(file); 
     bmp.compress(Bitmap.CompressFormat.PNG, 90, os); 
    } catch (IOException e) 
    { 
     // Unable to create file, likely because 
     // external storage is 
     // not currently mounted. 
     Log.e("FileMan", "Error writing file", e); 
    } catch (Exception e) 
    { 
     e.printStackTrace(); 
     throw e; 
    } 
} 
+0

sytuacja ze mną jest prawie taka sama, chodzi o to, że może zapewniać niskie warunki pamięci . Jest oczywiście szansa, że ​​mam wycieki pamięci. – Danail

-2

można użyć do WebView do wyświetlania obrazów, ma buforowanie wbudowany. Dodatkowo obsługuje zoom 2-palcowy i przewijanie bez specjalnego kodu.

Powiązane problemy