android圖片三級緩存

**這只是一個android圖片三級緩存的原理,是我從視頻學到的,也是我自己整理一下,應對面試用的。真正用的話建議還是使用xutils.
建議把下面的四個類的代碼看一遍,對理解三級緩存有幫助**
這裏是一個自定義的圖片工具類
public class MyBitmapUtils {
    NetCacheUtils mNetCacheUtils;//網絡圖片工具
    LocalCacheUtils mLocalCacheUtils;//本地圖片工具類
    MemoryCacheUtils memoryCacheUtils;//內存圖片工具類

    public MyBitmapUtils() {
        memoryCacheUtils = new MemoryCacheUtils();
        mLocalCacheUtils = new LocalCacheUtils();
        mNetCacheUtils = new NetCacheUtils(mLocalCacheUtils, memoryCacheUtils);

    }

    //加載圖片的方法
    public void display(ImageView ivPic, String url) {
        ivPic.setImageResource(R.drawable.news_pic_default);//設置加載默認圖片
        Bitmap bitmap=null  ;

        //先從從內存中讀去圖片
        bitmap=memoryCacheUtils.getBitmapFromMemory(url);
        if(bitmap!=null){
            ivPic.setImageBitmap(bitmap);
            return ;
        }
        //從本地sd卡中讀去圖片
        bitmap=mLocalCacheUtils.getBitmapFromLocal(url);
        if(bitmap!=null){
        //如果讀到了圖片
            ivPic.setImageBitmap(bitmap);
            memoryCacheUtils.setBitmaptoMemory(url, bitmap);//將圖片保存在內存中
        return;
        }
        //從網絡中讀去圖片
        mNetCacheUtils.getBitmapFormNet(ivPic, url);
    }
}

接下來是三個讀取圖片工具類

/*從網絡讀取圖片*/
public class NetCacheUtils {
    private LocalCacheUtils mlocalCacheUtils;//本地
    private MemoryCacheUtils mMemoryCacheUtils;//內存

    public NetCacheUtils(LocalCacheUtils localCacheUtils,
            MemoryCacheUtils memoryCacheUtils) {
        mlocalCacheUtils = localCacheUtils;
        mMemoryCacheUtils = memoryCacheUtils;
    }

    // 從網絡下載圖片
    public void getBitmapFormNet(ImageView ivPic, String url) {
        new BitmapTask().execute(ivPic, url);//啓動AsyncTask,參數會在doInbackground中獲取 會調用下面的doInBackground(Object... params)等等方法。這可以看作是一個啓動方法
    }

    class BitmapTask extends AsyncTask<Object, Void, Bitmap> {
        private ImageView ivPic;
        private String url;

        // 後臺耗時方法在此執行,子線程
        @Override
        protected Bitmap doInBackground(Object... params) {
            ivPic = (ImageView) params[0];
            url = (String) params[1];
            ivPic.setTag(url);// 將url和imageview綁定
            return downloadBitmap(url);//自己寫的函數,在下面被調用
        }

        // 更新進度,主線程
        @Override
        protected void onProgressUpdate(Void... values) {

            super.onProgressUpdate(values);
        }

        // 耗時方法結束後,執行此方法,主線程
        //也就是下載圖片結束後
        @Override
        protected void onPostExecute(Bitmap result) {
            if(result!=null){
                String bindUrl=(String) ivPic.getTag();
                if(url.equals(bindUrl)){//確保圖片設置給了正確的imageview
                    ivPic.setImageBitmap(result);
                    mlocalCacheUtils.setBitmapTocal(url, result);//將圖片保存到本地
                    mMemoryCacheUtils.setBitmaptoMemory(url, result);// 將圖片保存在內存
                    System.out.println("從網絡緩存讀取圖片了");

                }

            }
            super.onPostExecute(result);
        }
    }

    // 從網絡下載圖片
    private Bitmap downloadBitmap(String url) {
        HttpURLConnection conn = null;
        try {
            conn = (HttpURLConnection) new URL(url).openConnection();
            conn.setConnectTimeout(5000);
            conn.setReadTimeout(5000);
            conn.setRequestMethod("GET");
            conn.connect();
            int responseCode = conn.getResponseCode();
            if (responseCode == 200) {
                InputStream inputStram = conn.getInputStream();

                // 圖片壓縮處理
                BitmapFactory.Options option = new BitmapFactory.Options();
                option.inSampleSize = 2;// 寬高都壓縮爲原來的二分之一,此參數需要根據圖片要展示的大小來確定
                option.inPreferredConfig = Bitmap.Config.RGB_565;// 設置圖片格式
                Bitmap bitmap = BitmapFactory.decodeStream(inputStram, null,
                        option);

                return bitmap;
            }

        } catch (Exception e) {

            e.printStackTrace();
        } finally {

            conn.disconnect();
        }
        return null;

    }

}

本地緩存類

//本地緩存
 class LocalCacheUtils {

     public  static final String CACHE_PATH=Environment.getExternalStorageDirectory().getAbsolutePath()+"/zhbj_cache_52";//圖片存到sd卡中的地址
    // 從本地sdcard讀圖片
    public Bitmap getBitmapFromLocal(String url) {
     try{
     //存的時候把圖片的的地址用MD5加密後作爲存儲的名字,所以取得時候也要把地址加密。
        String filename=MD5Encoder.encode(url);
        File file=new File(CACHE_PATH,filename);
        if(file.exists()){
            Bitmap bitmap=BitmapFactory.decodeStream(new FileInputStream(file));
            return bitmap;
        }

     }
     catch(Exception e){

        e.printStackTrace(); 
     }
        return null;
    }

    // 向sdcard寫圖片
    public void setBitmapTocal(String url,Bitmap bitmap) {
        String filename;
        try {
            filename = MD5Encoder.encode(url);
            File file=new File(CACHE_PATH, filename);
            File parentFile=file.getParentFile();
            if(!parentFile.exists()){
                //如果文件夾不存在,創建文件夾
                parentFile.mkdir();
                //將圖片保存在本地
                bitmap.compress(CompressFormat.JPEG, 100,
                        new FileOutputStream(file));
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

內存緩存

public class MemoryCacheUtils {
    // private HashMap<String , SoftReference<Bitmap>> mMemoryCache=new
    // HashMap<String, SoftReference<Bitmap>>();


/*異步加載圖片的例子,網上也比較多,大部分用了HashMap<String, SoftReference<Drawable>> imageCache ,但是現在已經不再推薦使用這種方式了,因爲從 Android 2.3 (API Level 9)開始,垃圾回收器會更傾向於回收持有軟引用或弱引用的對象,這讓軟引用和弱引用變得不再可靠。另外,Android 3.0 (API Level 11)中,圖片的數據會存儲在本地的內存當中,因而無法用一種可預見的方式將其釋放,這就有潛在的風險造成應用程序的內存溢出並崩潰,所以我這裏用得是LruCache來緩存圖片,當存儲Image的大小大於LruCache設定的值,系統自動釋放內存,這個類是3.1版本中提供的,如果你是在更早的Android版本中開發,則需要導入android-support-v4的jar包(這裏要注意咯)*/

    private LruCache<String, Bitmap> mMemoryCache;

    public MemoryCacheUtils() {
        long maxMemory = Runtime.getRuntime().maxMemory() / 8;// 獲取最大內存模擬器默認是16M
        mMemoryCache = new LruCache<String, Bitmap>((int) maxMemory) {

            @Override
            protected int sizeOf(String key, Bitmap value) {
                int byteCount = value.getRowBytes() * value.getHeight();// 獲取圖片佔用內存大小
                return byteCount;
            }

        };
    }

    // 從內存中讀數據
    public Bitmap getBitmapFromMemory(String url) {
        // 防止內存溢出,但下面的方法實際中不用
        // SoftReference<Bitmap> softReference=mMemoryCache.get(url);
        // if(softReference!=null){
        // Bitmap bitmap=softReference.get();
        // return bitmap;
        //
        //
        // }
        return mMemoryCache.get(url);

    }

    // 寫內存
    public  void setBitmaptoMemory(String url, Bitmap bitmap) {
        // SoftReference<Bitmap> softReference = new
        // SoftReference<Bitmap>(bitmap);
        // mMemoryCache.put(url, softReference);
        mMemoryCache.put(url, bitmap);
    }
}

調用舉例
private MyBitmapUtils myutils;
myutils.display(holder.ivPic,item.listimage );

//註釋 自己的bitmaoutils
//註釋 holder.ivPic 一個holder中的imgivew.
//註釋 item.listimage 一個圖片的地址
只需知道兩個參數一個是imageivew,一個是url就行

首先會從內存中找圖片,內存中沒有,會在從本地sd卡中讀取,如果從本地找到圖片,會顯示到imgview中,然後順便存到內存中,如果沒有在從網絡中讀取,從網絡中讀到流後,生成bitmap 順便存到內存與sd卡中。




  我只是一個菜鳥,視頻裏就是這麼講的,怎麼實際中要用的話,建議用xutils,因爲三級緩存它幫你實現了。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章