Not: Resim yüklemeyle ilgili en iyi uygulamaları izleyen çeşitli kitaplıklar vardır. Resimleri en optimize şekilde yüklemek için uygulamanızda bu kitaplıkları kullanabilirsiniz. Resimleri mümkün olduğunca hızlı ve sorunsuz bir şekilde yükleyip gösteren Glide kitaplığını öneririz. Diğer popüler görüntü yükleme kitaplıkları arasında Square'den Picasso, Instacart'tan Coil ve Facebook'tan Fresco yer alır. Bu kitaplıklar, Android'de bit eşlemlerle ve diğer görüntü türleriyle ilişkili karmaşık görevlerin çoğunu basitleştirir.
Resimler çeşitli şekillerde ve boyutlarda olabilir. Çoğu durumda bu boyut, tipik bir uygulama kullanıcı arayüzü için gerekenden daha büyüktür. Örneğin, sistem Galeri uygulaması Android cihazınızın kamerasıyla çekilen fotoğrafları görüntüler. Bu fotoğraflar genellikle cihazınızın ekran yoğunluğundan çok daha yüksek çözünürlüktedir.
Sınırlı bellekle çalıştığınız düşünülürse, ideal olarak yalnızca belleğe daha düşük çözünürlüklü bir sürüm yüklemek istersiniz. Düşük çözünürlüklü sürüm, onu görüntüleyen kullanıcı arayüzü bileşeninin boyutuyla eşleşmelidir. Daha yüksek çözünürlüğe sahip bir görüntü, görünür bir avantaj sağlamaz ancak yine de değerli belleği kaplar ve ölçeklemenin artması nedeniyle ek performans yüküne neden olur.
Bu derste, belleğe daha küçük bir alt örneklenmiş sürüm yükleyerek uygulama başına bellek sınırını aşmadan büyük bit eşlemlerin kodunu çözmeyi öğreneceksiniz.
Bit Eşlem Boyutlarını ve Türünü Okuma
BitmapFactory
sınıfı, çeşitli kaynaklardan Bitmap
oluşturmak için çeşitli kod çözme yöntemleri (decodeByteArray()
, decodeFile()
, decodeResource()
vb.) sağlar. Görüntü veri kaynağınıza göre en uygun kod çözme yöntemini seçin. Bu yöntemler, oluşturulan bit eşlem için bellek ayırmaya çalışır ve bu nedenle kolayca OutOfMemory
istisnasına yol açabilir. Her bir kod çözme yöntemi türünün, BitmapFactory.Options
sınıfı aracılığıyla kod çözme seçeneklerini belirtmenize olanak tanıyan ek imzaları vardır. Kod çözerken inJustDecodeBounds
özelliğinin true
olarak ayarlanması, bellek ayırmanın önüne geçer. Bit eşlem nesnesi için null
döndürülür ancak outWidth
, outHeight
ve outMimeType
değerleri ayarlanır. Bu teknik, bit eşlemin oluşturulmasından (ve bellek ayrılmasından) önce resim verilerinin boyutlarını ve türünü okumanıza olanak tanır.
Kotlin
val options = BitmapFactory.Options().apply { inJustDecodeBounds = true } BitmapFactory.decodeResource(resources, R.id.myimage, options) val imageHeight: Int = options.outHeight val imageWidth: Int = options.outWidth val imageType: String = options.outMimeType
Java
BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeResource(getResources(), R.id.myimage, options); int imageHeight = options.outHeight; int imageWidth = options.outWidth; String imageType = options.outMimeType;
java.lang.OutOfMemory
istisnalarını önlemek için bit eşlemin kodunu çözmeden önce boyutlarını kontrol edin. Aksi halde, kaynağın mevcut belleğe rahatça sığan, tahmin edilebilir boyutta resim verileri sağlayacağına güvenmiyorsanız
Belleğe Ölçeklendirilmiş Sürüm Yükleme
Artık resim boyutları bilindiği için, tam resmin belleğe mi yükleneceğine yoksa bunun yerine alt örneklenmiş sürümün mi yükleneceğine karar vermek için kullanılabilir. Dikkate almanız gereken bazı faktörler şunlardır:
- Bellekteki tam resmin yüklenmesi için tahmini bellek kullanımı.
- Uygulamanızın diğer bellek gereksinimleri göz önünde bulundurulduğunda, bu resmi yüklemek için ayırmak istediğiniz bellek miktarı.
- Resmin yükleneceği hedef
ImageView
veya kullanıcı arayüzü bileşeninin boyutları. - Mevcut cihazın ekran boyutu ve yoğunluğu.
Örneğin, 1024x768 piksel boyutundaki bir resim, ImageView
boyutunda 128x96 piksel boyutunda küçük resimde görüntülenecekse belleğe yüklenmeye değmez.
Kod çözücüye, belleğe daha küçük bir sürüm yükleyerek görüntüyü alt örneklemsini bildirmek için BitmapFactory.Options
nesnenizde inSampleSize
değerini true
olarak ayarlayın. Örneğin, çözünürlüğü 2048x1536 olan ve inSampleSize
değeri 4 ile çözülen bir resim, yaklaşık 512x384 boyutunda bir bit eşlem oluşturur. Bunun belleğe yüklenmesi, tam resim için 12 MB yerine 0,75 MB kullanır (ARGB_8888
öğesinin bit eşlem yapılandırması olduğu varsayılır). Hedef genişlik ve yüksekliğe göre ikinin üssü olan örnek boyutu değerini hesaplamaya yönelik bir yöntem aşağıda verilmiştir:
Kotlin
fun calculateInSampleSize(options: BitmapFactory.Options, reqWidth: Int, reqHeight: Int): Int { // Raw height and width of image val (height: Int, width: Int) = options.run { outHeight to outWidth } var inSampleSize = 1 if (height > reqHeight || width > reqWidth) { val halfHeight: Int = height / 2 val halfWidth: Int = width / 2 // Calculate the largest inSampleSize value that is a power of 2 and keeps both // height and width larger than the requested height and width. while (halfHeight / inSampleSize >= reqHeight && halfWidth / inSampleSize >= reqWidth) { inSampleSize *= 2 } } return inSampleSize }
Java
public static int calculateInSampleSize( BitmapFactory.Options options, int reqWidth, int reqHeight) { // Raw height and width of image final int height = options.outHeight; final int width = options.outWidth; int inSampleSize = 1; if (height > reqHeight || width > reqWidth) { final int halfHeight = height / 2; final int halfWidth = width / 2; // Calculate the largest inSampleSize value that is a power of 2 and keeps both // height and width larger than the requested height and width. while ((halfHeight / inSampleSize) >= reqHeight && (halfWidth / inSampleSize) >= reqWidth) { inSampleSize *= 2; } } return inSampleSize; }
Not: İki değerin kuvveti hesaplanır çünkü kod çözücü, inSampleSize
belgelerinde belirtildiği gibi, nihai değeri ikinin en yakın kuvvetine yuvarlayarak nihai değeri kullanır.
Bu yöntemi kullanmak için önce kodu inJustDecodeBounds
true
olarak ayarlayıp seçenekleri geçirin, ardından yeni inSampleSize
değerini ve inJustDecodeBounds
değerini false
olarak ayarlayıp tekrar kodu çözün:
Kotlin
fun decodeSampledBitmapFromResource( res: Resources, resId: Int, reqWidth: Int, reqHeight: Int ): Bitmap { // First decode with inJustDecodeBounds=true to check dimensions return BitmapFactory.Options().run { inJustDecodeBounds = true BitmapFactory.decodeResource(res, resId, this) // Calculate inSampleSize inSampleSize = calculateInSampleSize(this, reqWidth, reqHeight) // Decode bitmap with inSampleSize set inJustDecodeBounds = false BitmapFactory.decodeResource(res, resId, this) } }
Java
public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId, int reqWidth, int reqHeight) { // First decode with inJustDecodeBounds=true to check dimensions final BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeResource(res, resId, options); // Calculate inSampleSize options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); // Decode bitmap with inSampleSize set options.inJustDecodeBounds = false; return BitmapFactory.decodeResource(res, resId, options); }
Bu yöntem, aşağıdaki örnek kodda gösterildiği gibi, 100x100 piksel boyutunda küçük resim görüntüleyen bir ImageView
öğesine rastgele büyük boyutlu bit eşlemlerin yüklenmesini kolaylaştırır:
Kotlin
imageView.setImageBitmap( decodeSampledBitmapFromResource(resources, R.id.myimage, 100, 100) )
Java
imageView.setImageBitmap( decodeSampledBitmapFromResource(getResources(), R.id.myimage, 100, 100));
Gerektiğinde uygun BitmapFactory.decode*
yöntemini kullanarak diğer kaynaklardan bit eşlemlerin kodunu çözmek için benzer bir süreç izleyebilirsiniz.