Android高效顯示圖片詳解(一)

前提與解釋:html

      安卓平臺做爲一款移動端的應用操做平臺,其內存容量是十分有限的,內存資源是十分珍貴的,是沒法與傳統的桌面平臺相比的,所以,在安卓平臺下一樣的圖片操做與處理都要十分謹慎,不然你的程序能夠迅速地消耗可用內存的預算,最終因爲OutOfMemory致使程序崩潰掉。如下有三個緣由說明了咱們爲何要謹慎:java

(1)安卓平臺下對應用可以使用的系統資源都作出了限制,標準安卓系統下,一個應用程序可用的最大內存爲16M,一些第三方ROMandroid

可能會上調這一限制,可是做爲應用來講必定要控制本身的內存用量,這並非能夠無限制使用的。ios


(2)一張高分辨圖片的內容耗用量是驚人的,例如,Galaxy Nexus的攝像頭在拍攝2592X1936像素(5百萬像素)。若是位圖使用併發

的是配置ARGB_8888(默認的Android 2.3開始),那麼此圖像加載到內存佔用約19MB的內存(2592 * 1936 * 4字節),直接就耗this

盡了在某些設備上的每一個應用程序的內存上限。spa


(3)安卓應用程序的一些控件常常須要幾個位圖一塊兒加載。例如ListView,GridView,ViewPager等控件,而且在使用中還要快速code

的滑動,要及時對圖片進行更新與回收,更加增長了圖片處理的難度。htm


解決辦法:圖片

一,如何去加載與顯示大圖:

          其實,在安卓這樣內存有限的平臺上,是沒有必要按照原始尺寸把一張大圖徹底加載進來的,只須要加載與咱們顯示控件相匹配的尺寸就行,多了只會浪費咱們寶貴的內存。所以在加載圖片時,咱們按照咱們須要顯示的大小對原始圖片再採樣就OK了。同時咱們也能夠根據咱們所可以使用的內存大小來對圖片進行解碼,按照咱們可以承受的尺寸與分辨率來處理,保證圖片所佔用的內存在咱們可支配的範圍以內,也就避免了OOM的問題。


第一步:咱們須要獲取原始圖片的相關尺寸,分辨率等數據

                   能夠利用BitmapFactory的Options來達到這一目的,解碼圖片時能夠先把inJustDecodeBounds的值設爲true,這樣並無真正的去解碼圖片,不佔用內存,可是咱們卻能夠在這個過程當中獲取圖片的寬,高以及類型,代碼以下:

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;

 


第二步:獲取原始的圖片尺寸後,根據目標計算縮放比例係數,代碼以下:

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) {
        // Calculate ratios of height and width to requested height and width
        final int heightRatio = Math.round((float) height / (float) reqHeight);
        final int widthRatio = Math.round((float) width / (float) reqWidth);
        // Choose the smallest ratio as inSampleSize value, this will guarantee
        // a final image with both dimensions larger than or equal to the
        // requested height and width.
        inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
    }
    return inSampleSize;
}

官方文檔中說,inSampleSize這個屬性最好是2的倍數,這樣處理更快,效率更高。。。


第三步:開始對圖片進行解碼,代碼以下:

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

 


注意,真正解碼時須要把inJustDecodeBounds屬性重置爲false,這樣就能夠把一張十分巨大的圖輕鬆顯示在一個100x100的ImageView中了

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


固然,你也能夠用來加載顯示其餘來源的圖片,而不是例子中資源文件中的,下一講咱們研究ListView,GridView中的多圖片併發顯示問題。

轉載自移動微技

相關文章
相關標籤/搜索