Android學習筆記 – BitmapFun解析

如果圖片資源是靜態的,當我們要在View上顯示圖片時,隻需要簡單的將圖片賦值給ImageView就可以瞭,但如果需要瀏覽網絡上的圖片時該如何做呢?有可能圖片很大,有可能網速很慢並且不穩定,這種情況下該如何增加用戶體驗。Android官方的BitmapFun示例程序已經給瞭我們很好的解決方法 – 其實萬變不離其中,還是采用瞭提升性能的兩種常用方法:異步和緩存。

 

不多說我們先來看BitmapFun的主要類圖:

 

 

ImageWorker:這個是加載圖片的核心類,建議大傢看源代碼從這個類看起。它的主要功能是從內存/磁盤緩存中加載圖片,或者是從網絡上下載。這裡第一要使用緩存,第二從網絡上下載,必然要使用異步線程,所以這裡從類圖中大傢也可以看到它有兩個關聯類BitmapWorkerTask(繼承自AsynTask)和ImageCache, 分別用來處理異步和緩存。

 

ImageWorker提供給外部的主要接口是loadImage方法 – 加載圖片,如果內存中有,直接加載。否則使用異步線程(BitmapWorkerTask)後臺加載 – 從磁盤或者是網絡上下載

 

 public void loadImage(Object data, ImageView imageView) {}

 

 

BitmapWorkerTask: 異步處理圖片 – 下載並綁定圖片

 

ImageCache: 圖片的緩存處理,這裡使用瞭二級緩存: 內存和磁盤。這裡從類圖也可以看到它有一個關聯類DiskLruCache。

 

DiskLruCache: 關於這個類網上有一些詳盡的解釋文章。在看這個類時切忌一開始就看代碼,一定要先看類的說明,主要是journal file的格式,否則你就很難明白它的一些代碼為什麼那麼寫。這裡把幾個重點提一下,相信大傢再看代碼會容易的多

 

  1 前5行是固定(最開始是固定的5行,值是可變)

 

  2 一條記錄用類Entry來描述,一條記錄就是一個Entry實例, 比如 CLEAN 3400330d1dfc7f3f7f4b8d4d803dfcf6 832 21054 在程序中就是一個Entry實例

 

  3 Editor是Entry的操作器,用來讀寫數據

 

 

     *     libcore.io.DiskLruCache

     *     1

     *     100

     *     2

     *

     *     CLEAN 3400330d1dfc7f3f7f4b8d4d803dfcf6 832 21054

     *     DIRTY 335c4c6028171cfddfbaae1a9c313c52

     *     CLEAN 335c4c6028171cfddfbaae1a9c313c52 3934 2342

     *     REMOVE 335c4c6028171cfddfbaae1a9c313c52

     *     DIRTY 1ab96a171faeeee38496d8b330771a7a

     *     CLEAN 1ab96a171faeeee38496d8b330771a7a 1600 234

     *     READ 335c4c6028171cfddfbaae1a9c313c52

     *     READ 3400330d1dfc7f3f7f4b8d4d803dfcf6

     *

 

 

寫到這裡先停一下,我們再次說明ImageWorker的功能,從內存直接加載或異步加載(從磁盤緩存或網絡下載)圖片。緩存的實現-ImageCache, 異步加載的實現 – BitmapWorkerTask。是不是比較清晰瞭。

 

 

 

接下來繼續往下看:

 

ImageResizer:繼承自ImageWorker,可能有的童鞋會問ImageWorker不是已經實現異步和緩存瞭嗎,這個類是幹嘛的呢?這個主要是根據給定的大小對Image做調整。比如當圖片太大時,不能簡單的加載到內存,需要做大小調整處理。

 

這裡對它的幾個主要接口說明一下:

 

  setImageSize:設置圖片要調整的大小

 

  calculateInSampleSize: 計算縮放比例 – 根據原圖大小和要調整後的大小計算

 

  decodeSampledBitmapFrom***:得到調整大小後的圖片,,這裡好幾個方法,數據源不一樣而已,沒啥大區別。

 

 

 

ImageFetcher:繼承自ImageResizer。從網絡下載圖片。這裡要澄清一點,processBitmap在ImageWorker中是一個抽象方法,並沒有實現體,在本示例中,是在ImageFetcher中實現的。之所以這樣設計,是因為圖片的來源是不確定和可變的,有可能從網絡下載,有可能從本地數據庫獲取。

 

    protected abstract Bitmap processBitmap(Object data);

 

 

 最後就是在View這一層如何來使用瞭,從類圖中可以看出,View這一層基本上操作ImageFetcher就可以瞭。以IamgeGridFragment為例:

 

1 在onCreate中實例化ImageFetcher,並且添加緩存處理實例

 

 

@Override

    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        // The ImageFetcher takes care of loading images into our ImageView children asynchronously

        mImageFetcher = new ImageFetcher(getActivity(), mImageThumbSize);

        mImageFetcher.setLoadingImage(R.drawable.empty_photo);

        mImageFetcher.addImageCache(getActivity().getSupportFragmentManager(), cacheParams);

    }

 

2 onCreateView中異步加載圖片

 

 @Override

    public View onCreateView(

           

        mGridView.setAdapter(mAdapter);

   }      

ImageAdapter.getView – 調用ImageFetcher.loadImage加載圖片

 

@Override

        public View getView(int position, View convertView, ViewGroup container) {

            mImageFetcher.loadImage(Images.imageThumbUrls[position – mNumColumns], imageView);

            return imageView;

        }

3 在destroty時候關閉緩存

 

@Override

    public void onDestroy() {

        super.onDestroy();

        mImageFetcher.closeCache();

發佈留言