溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Android圖片三級(jí)緩存策略

發(fā)布時(shí)間:2020-06-03 05:11:01 來(lái)源:網(wǎng)絡(luò) 閱讀:926 作者:jkmimi 欄目:移動(dòng)開(kāi)發(fā)

1.簡(jiǎn)介

Android緩存原理都是一樣,可以自己封裝。

三級(jí)緩存:

 1.內(nèi)存緩存:緩存在內(nèi)存中,基于LRU(least recently used )算法,機(jī)器重啟消失。

 2.本地緩存。緩存在本地中。一般鍵值對(duì)形式。(url,filepath)

 3.網(wǎng)絡(luò)緩存。從網(wǎng)絡(luò)加載資源,然后緩存在內(nèi)存、本地中。

2.實(shí)現(xiàn)步驟

2.1 內(nèi)存緩存:

[java] view plain copy
public class MemoryCacheUtils {
private LruCache<String,Bitmap> mMemoryCache;
public MemoryCacheUtils(){
long maxMemory = Runtime.getRuntime().maxMemory()/8;//得到手機(jī)最大允許內(nèi)存的1/8,即超過(guò)指定內(nèi)存,則開(kāi)始回收
//需要傳入允許的內(nèi)存最大值,虛擬機(jī)默認(rèn)內(nèi)存16M,真機(jī)不一定相同
mMemoryCache=new LruCache<String,Bitmap>((int) maxMemory){
//用于計(jì)算每個(gè)條目的大小
@Override
protected int sizeOf(String key, Bitmap value) {
int byteCount = value.getByteCount();
return byteCount;
}
};
}
/**

  • 從內(nèi)存中讀圖片
  • @param url
    /
    public Bitmap getBitmapFromMemory(String url) {
    //Bitmap bitmap = mMemoryCache.get(url);//1.強(qiáng)引用方法
    /
    2.弱引用方法
    SoftReference<Bitmap> bitmapSoftReference = mMemoryCache.get(url);
    if (bitmapSoftReference != null) {
    Bitmap bitmap = bitmapSoftReference.get();
    return bitmap;
    }
    */
    if(url==null||"".equals(url)){
    return null;
    }
    Bitmap bitmap = mMemoryCache.get(url);

      return bitmap;  

    }
    /**

  • 往內(nèi)存中寫圖片
  • @param url
  • @param bitmap
    /
    public void setBitmapToMemory(String url, Bitmap bitmap) {
    //mMemoryCache.put(url, bitmap);//1.強(qiáng)引用方法
    /
    2.弱引用方法
    mMemoryCache.put(url, new SoftReference<>(bitmap));
    */
    mMemoryCache.put(url,bitmap);
    }
    }
    2.2本地緩存

[java] view plain copy
public class LocalCacheUtils {
private static final String CACHE_PATH= Environment.getExternalStorageDirectory().getAbsolutePath()+"/my/images";
/**

  • 從本地讀取圖片
  • @param url
    */
    public Bitmap getBitmapFromLocal(String url){
    String fileName = null;//把圖片的url當(dāng)做文件名,并進(jìn)行MD5加密
    try {
    fileName = MD5Encoder.encode(url); //這里加不加密無(wú)所謂
    File file=new File(CACHE_PATH,fileName);
    Bitmap bitmap = BitmapFactory.decodeStream(new FileInputStream(file));
    return bitmap;
    } catch (Exception e) {
    e.printStackTrace();
    }
    return null;
    }

    /**

  • 從網(wǎng)絡(luò)獲取圖片后,保存至本地緩存
  • @param url
  • @param bitmap
    */
    public void setBitmapToLocal(String url,Bitmap bitmap){
    try {

         String fileName = MD5Encoder.encode(url);//把圖片的url當(dāng)做文件名,并進(jìn)行MD5加密  
         File file=new File(CACHE_PATH,fileName);  
    
         //通過(guò)得到文件的父文件,判斷父文件是否存在  
         File parentFile = file.getParentFile();  
         if (!parentFile.exists()){  
             parentFile.mkdirs();  
         }  
         //把圖片保存至本地  
         bitmap.compress(Bitmap.CompressFormat.JPEG,100,new FileOutputStream(file));  
     } catch (Exception e) {  
         e.printStackTrace();  
     }  

    }
    }
    2.3網(wǎng)絡(luò)緩存

[java] view plain copy
public class NetCacheUtils {
private LocalCacheUtils mLocalCacheUtils;
private MemoryCacheUtils mMemoryCacheUtils;

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

}  
/** 
 * 從網(wǎng)絡(luò)下載圖片 
 * @param ivPic 顯示圖片的imageview 
 * @param url   下載圖片的網(wǎng)絡(luò)地址 
 */  
public void getBitmapFromNet(ImageView ivPic, String url) {  
    new BitmapTask().execute(ivPic, url);//啟動(dòng)AsyncTask  

}  

public void getBitmapFromNet(View ivPic, String url) {  
    new BitmapTask_view().execute(ivPic, url);//啟動(dòng)AsyncTask  

}  
public Bitmap getBitmapFromNet(final String url) {  
    //啟動(dòng)AsyncTask  
    return null;  
}  
/** 
 * AsyncTask就是對(duì)handler和線程池的封裝 
 * 第一個(gè)泛型:參數(shù)類型 
 * 第二個(gè)泛型:更新進(jìn)度的泛型 
 * 第三個(gè)泛型:onPostExecute的返回結(jié)果 
 */  
class BitmapTask extends AsyncTask<Object, Void, Bitmap> {  

    private ImageView ivPic;  
    private String url;  

    /** 
     * 后臺(tái)耗時(shí)操作,存在于子線程中 
     * @param params 
     * @return 
     */  
    @Override  
    protected Bitmap doInBackground(Object[] params) {  
        ivPic = (ImageView) params[0];  
        url = (String) params[1];  

        return downLoadBitmap(url);  
    }  

    /** 
     * 更新進(jìn)度,在主線程中 
     * @param values 
     */  
    @Override  
    protected void onProgressUpdate(Void[] values) {  
        super.onProgressUpdate(values);  
    }  

    /** 
     * 耗時(shí)方法結(jié)束后執(zhí)行該方法,主線程中 
     * @param result 
     */  
    @Override  
    protected void onPostExecute(Bitmap result) {  
        if (result != null) {  
            ivPic.setImageBitmap(result);  
            System.out.println("從網(wǎng)絡(luò)緩存圖片啦.....");  

            //從網(wǎng)絡(luò)獲取圖片后,保存至本地緩存  
            mLocalCacheUtils.setBitmapToLocal(url, result);  
            //保存至內(nèi)存中  
            mMemoryCacheUtils.setBitmapToMemory(url, result);  

        }  
    }  
}  
/** 
 * AsyncTask就是對(duì)handler和線程池的封裝 
 * 第一個(gè)泛型:參數(shù)類型 
 * 第二個(gè)泛型:更新進(jìn)度的泛型 
 * 第三個(gè)泛型:onPostExecute的返回結(jié)果 
 */  
@SuppressLint("NewApi")  
class BitmapTask_view extends AsyncTask<Object, Void, Bitmap> {  

    private View ivPic;  
    private String url;  

    /** 
     * 后臺(tái)耗時(shí)操作,存在于子線程中 
     * @param params 
     * @return 
     */  
    @Override  
    protected Bitmap doInBackground(Object[] params) {  
        ivPic = (View) params[0];  
        url = (String) params[1];  

        return downLoadBitmap(url);  
    }  

    /** 
     * 更新進(jìn)度,在主線程中 
     * @param values 
     */  
    @Override  
    protected void onProgressUpdate(Void[] values) {  
        super.onProgressUpdate(values);  
    }  

    /** 
     * 耗時(shí)方法結(jié)束后執(zhí)行該方法,主線程中 
     * @param result 
     */  
    @Override  
    protected void onPostExecute(Bitmap result) {  
        if (result != null) {  
            //ivPic.setImageBitmap(result);  
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {    
                //Android系統(tǒng)大于等于API16,使用setBackground    
                ivPic.setBackground(new BitmapDrawable(result));  
            } else {    
                //Android系統(tǒng)小于API16,使用setBackground    
                ivPic.setBackgroundDrawable(new BitmapDrawable(result));  
            }    

            System.out.println("從網(wǎng)絡(luò)緩存圖片啦.....");  

            //從網(wǎng)絡(luò)獲取圖片后,保存至本地緩存  
            mLocalCacheUtils.setBitmapToLocal(url, result);  
            //保存至內(nèi)存中  
            mMemoryCacheUtils.setBitmapToMemory(url, result);  

        }  
    }  
}  
/** 
 * 網(wǎng)絡(luò)下載圖片 
 * @param url 
 * @return 
 */  
public Bitmap downLoadBitmap(String url) {  
    HttpURLConnection conn = null;  
    try {  
        conn = (HttpURLConnection) new URL(url).openConnection();  
        conn.setConnectTimeout(5000);  
        conn.setReadTimeout(5000);  
        conn.setRequestMethod("GET");  

        int responseCode = conn.getResponseCode();  
        if (responseCode == 200) {  
            //圖片壓縮  
            BitmapFactory.Options options = new BitmapFactory.Options();  
            options.inSampleSize=2;//寬高壓縮為原來(lái)的1/2  
            options.inPreferredConfig=Bitmap.Config.ARGB_4444;  

            //Bitmap bitmap = BitmapFactory.decodeStream(conn.getInputStream(),null,options);  
            Bitmap bitmap=BitmapFactory.decodeStream(conn.getInputStream());  
            return bitmap;  
        }  
    } catch (IOException e) {  
        e.printStackTrace();  
    }catch (Exception e) {  
    } finally {  
        if(conn!=null){  
            conn.disconnect();  
        }  
    }  

    return null;  
}  

}
2.4外部寫一個(gè)bitmapUtils來(lái)調(diào)用它們。

[java] view plain copy
public class MyBitmapUtils {
private NetCacheUtils mNetCacheUtils;
private LocalCacheUtils mLocalCacheUtils;
private MemoryCacheUtils mMemoryCacheUtils;

public MyBitmapUtils(){  
    mMemoryCacheUtils=new MemoryCacheUtils();  
    mLocalCacheUtils=new LocalCacheUtils();  
    mNetCacheUtils=new NetCacheUtils(mLocalCacheUtils,mMemoryCacheUtils);  
}  
public Bitmap getBitmap(String url){  
    Bitmap bitmap=null;  
     bitmap=mMemoryCacheUtils.getBitmapFromMemory(url);  
    if(bitmap!=null){  
        return bitmap;  
    }  
    bitmap = mLocalCacheUtils.getBitmapFromLocal(url);  
    if(bitmap!=null){  
         mMemoryCacheUtils.setBitmapToMemory(url,bitmap);  
         return bitmap;  
    }  

     return bitmap;  
}  
public void disPlay(ImageView ivPic, String url) {  
    Bitmap bitmap;  
    //內(nèi)存緩存  
    bitmap=mMemoryCacheUtils.getBitmapFromMemory(url);  
    if (bitmap!=null){  
        ivPic.setImageBitmap(bitmap);  
       Log.d("iamgecache","從內(nèi)存獲取圖片啦.....--->"+url);  
        return;  
    }  

    //本地緩存  
    bitmap = mLocalCacheUtils.getBitmapFromLocal(url);  
    if(bitmap !=null){  
        ivPic.setImageBitmap(bitmap);  
        Log.d("iamgecache","從本地獲取圖片啦.....-->"+url);  
        //從本地獲取圖片后,保存至內(nèi)存中  
        mMemoryCacheUtils.setBitmapToMemory(url,bitmap);  
        return;  
    }  
    //網(wǎng)絡(luò)緩存  
    mNetCacheUtils.getBitmapFromNet(ivPic,url);  
    Log.d("iamgecache","從網(wǎng)絡(luò)獲取圖片啦.....-->"+url);  
}  

@SuppressLint("NewApi")  
public void disPlay(View ivPic, String url) {  
    Bitmap bitmap;  
    //內(nèi)存緩存  
    bitmap=mMemoryCacheUtils.getBitmapFromMemory(url);  
    if (bitmap!=null){  
        //ivPic.setImageBitmap(bitmap);  
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {    
            //Android系統(tǒng)大于等于API16,使用setBackground    
            ivPic.setBackground(new BitmapDrawable(bitmap));  
        } else {    
            //Android系統(tǒng)小于API16,使用setBackground    
            ivPic.setBackgroundDrawable(new BitmapDrawable(bitmap));  

        }    
        //ivPic.setBackground(new BitmapDrawable(bitmap));  

        Log.d("iamgecache","從內(nèi)存獲取圖片啦.....--->"+url);  
        return;  
    }  

    //本地緩存  
    bitmap = mLocalCacheUtils.getBitmapFromLocal(url);  
    if(bitmap !=null){  
    //    ivPic.setImageBitmap(bitmap);  

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {    
            //Android系統(tǒng)大于等于API16,使用setBackground    
            ivPic.setBackground(new BitmapDrawable(bitmap));  
        } else {    
            //Android系統(tǒng)小于API16,使用setBackground    
            ivPic.setBackgroundDrawable(new BitmapDrawable(bitmap));  
        }    
        //ivPic.setBackground(new BitmapDrawable(bitmap));  

        Log.d("iamgecache","從本地獲取圖片啦.....-->"+url);  
        //從本地獲取圖片后,保存至內(nèi)存中  
        mMemoryCacheUtils.setBitmapToMemory(url,bitmap);  
        return;  
    }  
    //網(wǎng)絡(luò)緩存  
    mNetCacheUtils.getBitmapFromNet(ivPic,url);  
  //  ivPic.setBackground(new BitmapDrawable(bitmap));  
    Log.d("iamgecache","從網(wǎng)絡(luò)獲取圖片啦....-->"+url);  
}  

}
個(gè)人封裝的網(wǎng)絡(luò)緩存框架的好處是便于修改,自己清楚流程.適合于一些對(duì)圖片質(zhì)量沒(méi)那么高要求而又需要緩存減少網(wǎng)絡(luò)訪問(wèn)的情景.

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI