Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> ImageLoad(三級緩存(NetCache,MemoryCache,DiskCache),開源框架,OOM)

ImageLoad(三級緩存(NetCache,MemoryCache,DiskCache),開源框架,OOM)

編輯:關於Android編程

一.前言

首先再說三級緩存之前我們首先了解一下垃圾回收機制

下面是目前我所了解的幾種引用關系

這裡寫圖片描述

(一).強引用(StrongReference)

  垃圾回收機制不會回收強引用所指向的內存,就算系統內存不足報出內存溢出(OOM)異常,導致系統崩潰
  垃圾回收機制也不會去回收強引用的內容來解決內存不足的問題.
//強引用,也就是一般引用,使用new關鍵詞新建出來的引用關系
ImageView imageview = new ImageView();

(二).軟引用(SoftReference)

如果一個對象只具有軟引用,則內存空間足夠,垃圾回收器就不會回收它;
如果內存空間不足了,就會回收這些對象的內存。只要垃圾回收器沒有回收它,該對象就可以被程序使用。
軟引用可用來實現內存敏感的高速緩存

(三).弱引用(WeakReference)

    弱引用與軟引用的區別在於:弱引用的對象擁有更短暫的生命周期。
    在垃圾回收器線程掃描它所管轄的內存區域的過程中,一旦發現了只具有弱引用的對象,
    不管當前內存空間足夠與否,都會回收它的內存。不過,由於垃圾回收器是一個優先級很低的線程, 
    因此不一定會很快發現那些只具有弱引用的對象。

(四).虛引用(PhantomReference)

    “虛引用”顧名思義,就是形同虛設,與其他幾種引用都不同,虛引用並不會決定對象的生命周期。
    如果一個對象僅持有虛引用,那麼它就和沒有任何引用一樣,在任何時候都可能被垃圾回收器回收。

二.三級緩存原理

真如下圖所示,
1.首先我們從內存中獲取bitmap,
2.1.如果獲取的bitmap != null,直接加載到ImageVIew
2.2.如果獲取的bitmap==null,那麼將繼續從硬盤獲取bitmap
3.1如果從硬盤獲取的bitmap !=null,加載到ImageView.同時將bitmap緩存到內存緩存中
3.2如果從硬盤獲取的bitmap == null,繼續從網絡獲取
4.1從網絡獲取到圖片,然後
4.2.加載到ImageVIew,緩存到硬盤,緩存到內存

這裡寫圖片描述<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxoMiBpZD0="三代碼實現">三.代碼實現

下面是真個項目的大概框架圖

這裡寫圖片描述

(一).BitMapUtils類

    public void disPlay(ImageView imageView, String url){
        if(this.memoryCache != null){
            bitmap = this.memoryCache.getBitmap(url);
            if(bitmap != null){
                imageView.setImageBitmap(bitmap);
                return ;
            }
        }
        if(config.isUseDiskCache()&&this.diskCache != null){
            bitmap = this.diskCache.getBitmap(url,imageView);
            if(bitmap != null){
                memoryCache.setBitmap(url,bitmap);
                imageView.setImageBitmap(bitmap);
                return;
            }
        }
        if(this.netCache != null){
            this.netCache.disPlay(imageView,url);

        }
    }

(二).三個緩存類

//1.內存緩存,使用LRUCache<Key,Values>
//使用此方法,能有效的避免內存緩存的溢出問題
//效果同使用軟引用(SoftReference)相當

    public MemoryCacheUtils(ImageLoadConfig config) {
        super(config,null, null, null);

        lruCache = new LruCache((int) config.getMaxMemory()){
            @Override//計算緩存文件已使用的大小
            protected int sizeOf(String key, Bitmap value) {
                return value.getRowBytes() * value.getHeight();
            }
        };
    }
    @Override
    public Bitmap getBitmap(String url) {
            return lruCache.get(url);
    }
    @Override
    public void setBitmap(String key, Bitmap value) {
        lruCache.put(key,value);
    }
}
//在內存緩存中也可以使用HashMap
//此種方法使用了軟引用,但是還是推薦使用LruCache

    SoftReference> softhashMap = new SoftReference>();
    public Bitmap getBitmap(String url){
        return softhashMap.get(url);
    }
    public void setBitmap(Bitmap bitmap,String url){
        softhashMap.set(url,bitmap);
    }

//2.硬盤緩存:

    public Bitmap getBitmap(String url){
        return BitmapFactory.decodeFiles(filePath);
    }
    public void setBitmap(Bitmap bitmap,String url){
        File dir = new File(config.getLOCAL_PATH());
            String fileName = MD5Encoder.encode(key);
            File cacheFile = new File(dir, fileName);
             // 參1:圖片格式;參2:壓縮比例0-100; 參3:輸出流
            value.compress(Bitmap.CompressFormat.JPEG, 100, new FileOutputStreamcacheFile));

    }
//3.網絡緩存,使用AsyncTask加載網絡圖片
 public Bitmap disPlay(final ImageView imageView, final String url) {
        asyncTask = new AsyncTask() {
            @Override
            protected void onPreExecute() {
                super.onPreExecute();
            }
            @Override
            protected void onProgressUpdate(Integer... values) {
                super.onProgressUpdate(values);
            }
            @Override//此方法存在於子線程可以直接進行延遲操作,加載網絡數據
            protected Bitmap doInBackground(String... params) {
            //從網絡下載圖片
                try {
                    URL url1 = new URL(params[0].toString());
                    HttpURLConnection conn = (HttpURLConnection) url1.openConnection();
                    conn.setRequestMethod("GET");
                    conn.setReadTimeout(config.getREAD_TIME());
                    conn.setConnectTimeout(config.getCONNECT_TIME());
                    if(conn.getResponseCode() == 200){
                        InputStream is = conn.getInputStream();
                        BitmapFactory.Options  options = new BitmapFactory.Options();
                        options.inSampleSize = config.getInSampleSize();
                        options.inPreferredConfig = Bitmap.Config.ARGB_4444;
                        bitmap = BitmapFactory.decodeStream(is,null,options);
                        conn.disconnect();
                        is.close();
                    }
                    return bitmap;
                } catch (Exception e) {
                    e.printStackTrace();
                }

                return null;
            }

            @Override
            protected void onPostExecute(Bitmap bitmap) {
                super.onPostExecute(bitmap);
                imageView.setImageBitmap(bitmap)//把加載來的bitmap設置給ImageView
                memoryCache.setBitmap(url,bitmap);//緩存到內存
                diskCache.setBitmap(url,bitmap);//保存到硬盤
            return bitmap;
    }

注:以上代碼均只寫了相關代碼,並沒有補全,如需詳細代碼,請參考github開源代碼

下載鏈接:點擊下載源碼

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