Büyük Bit Eşlemeleri Verimli Bir Şekilde Yükleme

Not: Takip eden çeşitli kitaplıklar vardır. en iyi uygulamaları paylaşacağım. Uygulamanızda bu kitaplıkları kullanarak şekilde yükleyebilirsiniz. Önerilerimiz: Kaydırma kitaplığını kullanabilirsiniz. Square'den Picasso, Instacart'tan Coil ve diğer popüler görüntü yükleme kitaplıkları arasında Fresk YouTube'dan. Bu kitaplıklar, programla ilişkili karmaşık görevlerin çoğunu bit eşlemler ve diğer resim türleriyle eşleşmesini sağlar.

Resimler tüm şekil ve boyutlarda olabilir. Çoğu zaman, standart bir boyuta göre gerekenden kullanıcı arayüzü. Örneğin, sistem Galeri uygulaması çekilen fotoğrafları (genellikle ekrandan çok daha yüksek çözünürlüklü) Android cihazlarınızın kamerasını kullanarak yoğunluğuna bağlıdır.

Sınırlı bellekle çalıştığınız için ideal olarak yalnızca daha düşük bir çözünürlük yüklemek istersiniz sürümü yüklüdür. Düşük çözünürlüklü sürüm, kullandığınız kullanıcı arayüzü bileşeninin görüntüler. Daha yüksek çözünürlüklü bir resim, görünür bir avantaj sağlamaz. Ancak yine de çalışır ve çalışırken ek performans nedeniyle ek performans yüküne neden olur. yardımcı olur.

Bu ders, uygulama başına boyutu aşmadan büyük bit eşlemlerin kodunu çözme konusunda size yol gösterir alt örneklenmiş bir sürüm yükleyerek daha küçük bir bellek sınırı belirleyebilirsiniz.

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.) sunar. Seç Resim veri kaynağınıza göre en uygun kod çözme yöntemini seçin. Bu yöntemler şunları dener: oluşturulan bit eşlem için bellek ayırır ve dolayısıyla kolayca bir OutOfMemory ile sonuçlanabilir kabul edersiniz. Her kod çözme yöntemi türünde, kod çözmeyi belirtmenizi sağlayan ek imzalar bulunur BitmapFactory.Options sınıfındaki seçenekler. Kod çözme sırasında inJustDecodeBounds özelliğini true olarak ayarlama Bellek tahsisini önler ve bit eşlem nesnesi için null değerini döndürür, ancak outWidth, outHeight ve outMimeType ayarlanır. Bu teknik, proje başlatma belgesindeki oluşturulmadan (ve bellek ayırmadan) önceki görüntü verilerinin boyutlarını ve türünü bit eşlem.

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 boyutlarını kontrol etmeden önce Size tahmin edilebilir boyutlu resim verileri sağlayacağı için mutlaka kaynağa güvenmediğiniz sürece bir çerçeve ve ekran görüntüsü alın.

Belleğe Aşağı Ölçeklendirilmiş Sürümü Yükleme

Resim boyutları artık bilindiği için tam resmin alt örneklenmiş bir sürümün yüklenmesi gerekip gerekmediğini kontrol edebilirsiniz. Paydaş analizine hazırlanırken şunları göz önünde bulundurun:

  • Bellekte tam resmin yüklenmesi için tahmini bellek kullanımı.
  • Başka herhangi bir bellek nedeniyle bu görüntüyü yüklemek için taahhüt etmek istediğiniz bellek miktarı olması şarttır.
  • Resimde gösterilen hedef ImageView veya kullanıcı arayüzü bileşeninin boyutları veriler yer alır.
  • Mevcut cihazın ekran boyutu ve yoğunluğu.

Örneğin, 1024x768 piksel boyutundaki bir resim daha sonra bitecekse, belleğe yüklemenin bir anlamı yoktur. ImageView içinde 128x96 piksel boyutunda küçük resim olarak gösterilir.

Kod çözücüye resmi alt örneklemesini bildirmek için belleğe daha küçük bir sürüm yükleyerek BitmapFactory.Options nesnenizde inSampleSize öğesini true olarak ayarlayın. Örneğin, 2048x1536 çözünürlüğünde, kodu inSampleSize/4 ile çözülür, sonuç olarak bit eşlem olarak göstermeyi sağlar. Bunu belleğe yüklemek, tam boyut için 12 MB yerine 0,75 MB kullanır (ARGB_8888 bit eşlem yapılandırması olduğu varsayılır). İşte hedef genişliğe ve ona göre ikinin kuvveti olan örneklem boyutunun değerini hesaplama yöntemi yükseklik:

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 dokümanlarına göre en yakın iki kuvvetine aşağı yuvarlayarak son değeri elde edersiniz.

Bu yöntemi kullanmak için önce true olarak ayarlanmış inJustDecodeBounds ile kodu çözün, seçenekleri iletin. aracılığıyla uygulayın ve ardından yeni inSampleSize değerini ve inJustDecodeBounds değerini false olarak ayarlanmış şekilde kullanarak kodu tekrar çö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 örnekte gösterildiği gibi 100x100 piksel boyutunda küçük resim görüntüleyen bir ImageView öğesine rastgele büyük boyutlu bir bit eşlemin yüklenmesini kolaylaştırır kod:

Kotlin

imageView.setImageBitmap(
        decodeSampledBitmapFromResource(resources, R.id.myimage, 100, 100)
)

Java

imageView.setImageBitmap(
    decodeSampledBitmapFromResource(getResources(), R.id.myimage, 100, 100));

Diğer kaynaklardaki bit eşlemlerin kodunu çözmek için, BitmapFactory.decode* yöntemini kullanın.