Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android異步加載全解析之大圖處理

Android異步加載全解析之大圖處理

編輯:關於Android編程

Android異步加載全解析之大圖處理

異步加載中非常重要的一部分就是對圖像的處理,這也是我們前面用異步加載圖像做演示例子的原因。一方面是因為圖像處理不好的話會非常占內存,而且容易OOM,另一方面,圖像也比文字要大,加載比較慢。所以,在講解了如何進行多線程、AsyncTask進行多線程加載後,先暫停下後面的學習,來對圖像的異步處理進行一些優化工作。

為什麼要對圖像處理

為什麼要對圖像進行處理,這是一個很直接的問題,一張圖像,不管你拿手機、相機、單反還是什麼玩意拍出來,它就有一定的大小,但是在不同的終端上,終端也有不同的大小,比如一張超高請無碼大圖,10M大小,在網頁中看著挺爽,全高清,毛孔都看得清。同樣一張圖片,如果放在4.7寸的手機上,當然,同樣還是一張高清無碼大圖,但這張圖片10M,在電腦上可能不算什麼,但在手機上,已經是非常大了,而這張圖片在手機上,你拼命看,也就是那樣,即使分辨率減少一半,你看上去也還是差不多。這就像所謂的視網膜屏、2k屏、4k屏,其實已經基本達到視覺分析的極限了,普通情況下,差別並不大。 但是,雖然你看著區別不大,但對系統來說,差別就非常大了,手機的內存,要像使用你藏的私房錢一樣,每一分都要三思而用。所以,我們在下載高分辨率的圖片的時候,可以對圖像進行壓縮,顯示上雖然沒有太大區別,但是卻幫系統節省了大量的私房錢。

BitmapFactory之inSampleSize

BitmapFactory是Android中提供的對圖像的解析方法,通過它的一些靜態方法,我們可以對圖像進行解析,例如從文件中解析——decodeFile;從資源中解析——decodeResource;從網絡中解析——decodeStream等等。 當我們從網絡上進行圖像下載的時候,看情況,是否需要對圖像進行壓縮,那麼如何在系統不加載圖像到內存之前,就獲取圖像的大小等參數呢?看上去非常矛盾,但系統給我們提供了一種簡單的解決方法。 BitmapFactory提供了BitmapFactory.Options參數,這個參數有一個inJustDecodeBounds屬性,當這個屬性為true的時候,我們就可以禁止系統加載圖像到內存,但是!!!這時候,Options參數中的圖像寬高、類型等屬性已經被賦值了,這樣,我們就實現了空手套白狼,哦,不對,是不使用內存就獲取圖像的屬性。
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;

在獲得了圖像的參數之後,我們就可以對圖像進行相應的處理了,例如我們顯示圖像的ImageView只有200 X 200 像素,而我們的圖片有800 X 800 像素,那你把這麼大的一張圖放到這麼小的ImageView中,有啥用呢?白白浪費了內存。OK,那麼下面我們就來對圖像進行壓縮,Options參數中給我們提供了這樣一個屬性——inSampleSize,這個屬性可以設置圖像的縮放比例,例如一張1000 X 1000像素的圖像,設置inSampleSize為5,意思就是把這個圖像縮放到了五分之一,即200 X 200 。OK,下面我們就通過這樣一個方法來對圖像進行優化,首先,我們需要創建一個方法來獲取到一個合適的inSampleSize:
/**
 * 獲取合適的inSampleSize
 * @param options
 * @param targetWidth 期望Width
 * @param targetHeight 期望Height
 * @return
 */
public static int getInSampleSize(BitmapFactory.Options options,
                                        int targetWidth, int targetHeight) {
    // 原始圖片的高度和寬度
    final int height = options.outHeight;
    final int width = options.outWidth;
    int inSampleSize = 1;
    if (height > targetHeight || width > targetWidth) {
        // 計算出實際寬高和目標寬高的比率
        final int heightRate = Math.round((float) height / (float) targetHeight);
        final int widthRate = Math.round((float) width / (float) targetWidth);
        inSampleSize = heightRate < widthRate ? heightRate : widthRate;
    }
    return inSampleSize;
}

方法非常簡單,就是通過期望長寬來獲取縮放的比例。下面我們就創建一個方法來獲取縮放後的圖像,這裡為了演示,我們只創建從資源文件中獲取圖像的方法:
/**
 * 使用targetWidth、targetHeight來獲取合適的inSampleSize
 * 並使用inSampleSize來縮放得到合適大小的圖像
 * @param res getResources()
 * @param resId id
 * @param targetWidth
 * @param targetHeight
 * @return
 */
public static Bitmap decodeSuitableBitmap(Resources res, int resId,
                                          int targetWidth, int targetHeight) {
    // 空手套白狼
    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeResource(res, resId, options);
    // 計算合適的inSampleSize
    options.inSampleSize = getInSampleSize(options, targetWidth, targetHeight);
    // 加載到內存
    options.inJustDecodeBounds = false;
    return BitmapFactory.decodeResource(res, resId, options);
}

通過調用decodeSuitableBitmap這樣一個方法,我們就可以非常簡單的將圖像進行壓縮。


 






  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved