Android: Bitmap recycle () nasıl çalışır?


90

Diyelim ki bir bitmap nesnesine bir görüntü yükledim.

Bitmap myBitmap = BitmapFactory.decodeFile(myFile);

Şimdi, gibi başka bir bitmap yüklersem ne olur?

myBitmap = BitmapFactory.decodeFile(myFile2);

İlk myBitmap'e ne olacak? Çöp Toplandı mı, yoksa başka bir bitmap'i yüklemeden önce el ile çöp toplamak zorunda mıyım, örn. myBitmap.recycle()?

Ayrıca, yolda geri dönüşüm yaparken büyük resimleri yüklemenin ve bunları arka arkaya görüntülemenin daha iyi bir yolu var mı?

Yanıtlar:



24

Sanırım sorun şudur: Android'in Honeycomb öncesi sürümlerinde, gerçek ham bitmap verileri VM belleğinde değil, bunun yerine yerel bellekte saklanır. Bu yerel bellek , karşılık gelen java Bitmapnesnesi GC'deyse serbest bırakılır .

Bununla birlikte , yerel belleğiniz tükendiğinde, dalvik GC tetiklenmez, bu nedenle uygulamanızın çok az java belleği kullanması mümkündür, bu nedenle dalvik GC hiçbir zaman çağrılmaz, ancak bit eşlemler için tonlarca yerel bellek kullanır bu da sonunda bir OOM hatasına neden olur.

En azından benim tahminim bu. Neyse ki Honeycomb'da ve sonrasında, tüm bitmap verileri sanal makinede depolanır, bu nedenle hiç kullanmak recycle()zorunda kalmazsınız . Ancak milyonlarca 2.3 kullanıcı için (parçalanma yumruk sallıyor ), recycle()mümkün olan her yerde kullanmalısınız (büyük bir güçlük). Veya alternatif olarak bunun yerine GC'yi çalıştırabilirsiniz.


21

Sonraki görüntüyü yüklemeden önce myBitmap.recycle () öğesini çağırmanız gerekecektir.

MyFile'ınızın kaynağına bağlı olarak (örneğin, orijinal boyutu üzerinde kontrolünüz olmayan bir şeyse), sadece rastgele bir sayıyı yeniden örneklemek yerine bir görüntüyü yüklerken görüntüyü ekran boyutuna ölçeklemelisiniz.

if (myBitmap != null) {
    myBitmap.recycle();
    myBitmap = null;
}
Bitmap original = BitmapFactory.decodeFile(myFile);
myBitmap = Bitmap.createScaledBitmap(original, displayWidth, displayHeight, true);
if (original != myBitmap)
    original.recycle();
original = null;

DisplayWidth & displayHeight'ı Aktivitemin başlangıcında başlattığım bir statikte önbelleğe alıyorum.

Display display = getWindowManager().getDefaultDisplay();
displayWidth = display.getWidth();
displayHeight = display.getHeight();

3
Recycle () 'ı çağırmanıza gerek yok, belleği hemen boşaltmak istiyorsanız bu sadece iyi bir fikirdir.
Karu

13
Kabul edilen cevap "Hafızayı en kısa sürede boşaltmak istiyorsanız, recycle () 'ı çağırmalısınız" der. Cevabınız "myBitmap.recycle () 'ı aramanız gerekecek" diyor. "Yapmalı" ve "ihtiyaç duymalı" arasında bir fark vardır ve ikincisi bu durumda yanlıştır.
Karu

1
Bağlam önemlidir. Soru, "Büyük resimleri yüklemenin ve onları yolda geri dönüştürmenin art arda göstermenin daha iyi bir yolu var mı?" İdi.
djunod

3
Android 4.1'den itibaren, createScaledBitmap bazı durumlarda orijinal olanla aynı örneği döndürebildiğinden yukarıdaki örnek bozulabilir. Bu, orijinali geri dönüştürmeden önce o orijinal! = MyBitmap'i kontrol etmeniz gerektiği anlamına gelir.
Jeremyfa 13

1
@Jeremyfa Orijinal ile aynı olan bir genişlik ve yükseklik belirtirseniz, yalnızca orijinal görüntüyü döndürür. Bu durumda ölçekleme tartışmalıdır, bu nedenle bazı işlemleri atlayıp bunun yerine orijinal görüntüyü geri döndürerek kaydedebilir. Yine de hiçbir şeyi "kırmamalı" ...
Jabari

11

Bitmap belleğe yüklendikten sonra, aslında iki bölümlü veriyle yapılmıştır. İlk bölüm bitmap hakkında bazı bilgiler içerir, diğer bölüm bitmap pikselleri hakkında bilgi içerir (bayt dizisi tarafından oluşturulur). Birinci kısım Java kullanılan hafızada, ikinci kısım C ++ kullanılmış hafızada bulunur. Birbirlerinin hafızasını doğrudan kullanabilir. Bitmap.recycle (), C ++ belleğini boşaltmak için kullanılır. Yalnızca bunu yaparsanız, GC java'nın bir kısmını toplar ve C'nin belleği her zaman kullanılır.


+1, belleğin neden anlık GC için uygun olmadığını açıklamanın ilginç ama çok iyi bir yolu - güzel bir.
Richard Le Mesurier

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.