高效的加載大圖片(二)

原文地址:http://developer.android.com/training/displaying-bitmaps/load-bitmap.html html

圖片有各類形狀和大小 ,大多數狀況他們都比界面所須要的來的大。例如,系統的Gallery應用展現照片經過設備的攝像頭獲取的分辨率比屏幕的分辨率要高許多。
java

因爲緩存的限制,理論上只要加載低分辨率版本的到緩存中。低分辨率版本須要適配組件的展現大小。一個更高分辨率版本不會帶來更多好處,反而要佔用更多的內存,還會在產生而外的開銷。android

這節課將介紹在解析大圖片時,經過加載一個更小的樣品版本到緩存中來解決應用的緩存限制。
緩存

讀取圖片的大小和類型
加密

BitmapFactory類提供了一些解碼方法(decodeByteArray(),decodeFile(),decodeResource())經過各類資源來建立一個圖片。基於圖片數據資源選擇合適的加密方法。這些方法會試圖爲圖片分配內存,所以會很容易致使內容溢出異常。每一種解碼方法均可以經過BitmapFactory.class類設置指定的配置。 設置inJustDecodeBounds爲true,解碼時就會避免佔用內存資源,bitmap會返回null,可是能夠設置outWidth、outHeight、outMimeType。這個技術容許讀取圖片的大小和類型來構建圖片。spa

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;

在解碼圖片時要確認他的大小,除非你確認圖片資源適合可用的資源。
code

加載一個縮小的版本到緩存中htm

如今知道了圖片的大小,能夠經過這個來決定是否加載完整的圖片或者是用他縮小的版原本替代。這裏有一些須要考慮的因素:
圖片

一、預估加載完整的圖片到內存中須要佔用的內存。內存

二、可以給圖片提供的內存數量

三、要加載圖片的組件的大小

四、當前設備的大小和分辨率

例如,加載一個1024x768像素的圖片到緩存用於一個128x96的ImageView組件展現,這是不值得的。

要讓解碼器加載一個低版本的圖片樣本到內存中,要設置BitmapFactory.Options屬性inSampleSize爲true。例如,一個圖片的分辨率爲2048x1536,解碼時設置inSampleSize爲4就會創造出一個近似512x384的圖片。這樣加載到緩存只會佔用0.75MB而不是完整圖片的12MB。下面是一個方法基於目標的寬度和高度計算圖片的樣本大小:

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;
}

使用這個方法首先要設置inJustDecodeBounds爲true在計算出新的inSampleSize後再設置inJustDecodeBounds爲false:

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);
}

使用這個方法能夠很容易的加載一個大的圖片到一個100x100像素展現的ImageView控件,就像下面代碼展現的同樣:

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

你也可使用BitmapFactory.decode*的其餘方法,利用類似的流程來加載資源。

相關文章
相關標籤/搜索