图片的三级缓存是指网络缓存,本地缓存,以及内存缓存。
从获得数据的顺序上将,显示网络缓存得到数据,紧接着存入本地缓存,在使用是放入内存缓存。
分别介绍三个缓存方式:
网络缓存最重要的是使用AsyncTask自定义bitmapTask,
AsyncTask三个重要的函数:
doInBackground:后台耗时方法,子线程中进行
onPostExecute:doInBackground结束后,执行该方法,主线程中运行的
onProgressUpdate:更新进度,在主线程中进行调用
主要思想是后台异步下载,得到结果之后在主线程中进行更新。
package com.example.zhihuibj.utils.bitmap; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import com.lidroid.xutils.HttpUtils; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.AsyncTask; import android.widget.ImageView; /* * 网络缓存 * */ public class NetCacheUtils { /* * */ private MyLoaclCacheUtils mLocalCacheUtils; private MemoryCacheUtils mMemoryCacheUtils; public NetCacheUtils(MyLoaclCacheUtils LocalCacheUtils, MemoryCacheUtils MemoryCacheUtils) { mLocalCacheUtils=LocalCacheUtils; mMemoryCacheUtils=MemoryCacheUtils; } public void getBitmapFromNet(ImageView ivPic, String url) { new BitmapTask().execute(ivPic,url);// 传入的参数在doInBackground中获取,启动AsyncTask } /* * 第一个参数:doInBackground 参数 * 第二个参数:onProgressUpdate 参数 * 第三个参数:onPostExecute 参数 */ 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,将URL与ImageView进行绑定 return DownLoadBitmap(url); } /* * doInBackground结束后,执行该方法,主线程中运行的 */ @Override protected void onPostExecute(Bitmap result) { if(result!=null) { String tagurl= (String) ivPic.getTag(); if(url.equals(tagurl))//确保图片是给定的URL ivPic.setImageBitmap(result); mLocalCacheUtils.SetBitMapToLoacl(url, result);//写入本地缓存 mMemoryCacheUtils.SetBitmaptoMemory(url, result); System.out.println("从网络获取图片...."); } } /* * 更新进度,在主线程中进行调用 */ @Override protected void onProgressUpdate(Void... values) { // TODO Auto-generated method stub super.onProgressUpdate(values); } } /* * 下载图片 */ private Bitmap DownLoadBitmap(String url) { HttpURLConnection con = null; try { con = (HttpURLConnection)new URL(url).openConnection(); con.setConnectTimeout(5000); con.setReadTimeout(5000); con.setRequestMethod("GET"); con.connect(); int responseCode = con.getResponseCode(); if(responseCode==200) { InputStream inputstream = con.getInputStream(); Bitmap bitmap = BitmapFactory.decodeStream(inputstream); return bitmap; } } catch (MalformedURLException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally{ con.disconnect(); } return null; } }
本地缓存主要是向sdcard中读写数据:
package com.example.zhihuibj.utils.bitmap; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Bitmap.CompressFormat; import android.os.Environment; public class MyLoaclCacheUtils { public static final String CACHE_PATH=Environment.getExternalStorageDirectory().getAbsolutePath()+"/zhihuibj_52"; /** * 从本地sdcard读图片 * @param url */ public Bitmap GetBitmapFromLoacl(String url){ String fileName; try { fileName = MD5Encode.encode(url); File file = new File(CACHE_PATH,fileName); if(file.exists()) { Bitmap bitmap = BitmapFactory.decodeStream(new FileInputStream(file)); return bitmap; } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } /** * 向sdcard写图片 * @param url * @param bitmap */ public void SetBitMapToLoacl(String url,Bitmap bitmap){ try { String fileName= MD5Encode.encode(url); File file = new File(CACHE_PATH,fileName); File parentFile = file.getParentFile(); if(!parentFile.exists()){//如果文件夹不存在,创建文件夹 parentFile.mkdirs(); } bitmap.compress(CompressFormat.JPEG, 100, new FileOutputStream(file));//将bitmap存到本地 } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
package com.example.zhihuibj.utils.bitmap; import java.io.UnsupportedEncodingException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import android.os.Message; public class MD5Encode { public static String encode(String string ) throws Exception { byte[] hash= MessageDigest.getInstance("MD5").digest(string.getBytes("UTF-8")); StringBuilder hex = new StringBuilder(hash.length*2); for( byte b: hash) { if((b&0xFF)<0x10) { hex.append("0"); } hex.append(Integer.toHexString(b&0xFF)); } return hex.toString(); } }
内存缓存主要用到的是:LruCache,并复写了sizeof方法来得到每个图片的大小。
package com.example.zhihuibj.utils.bitmap; import java.util.HashMap; import android.graphics.Bitmap; import android.support.v4.util.LruCache; public class MemoryCacheUtils { //private HashMap<String,Bitmap> mMemoryCache =new HashMap<String ,Bitmap>(); private LruCache<String,Bitmap> mMemoryCache; public MemoryCacheUtils(){ int maxSize=(int) (Runtime.getRuntime().maxMemory()/8); //获取模拟器分配给APP的内存大小的八分之一 mMemoryCache=new LruCache<String, Bitmap>(maxSize){ @Override protected int sizeOf(String key, Bitmap value) { return value.getHeight()*value.getWidth(); } }; } /** * 从内存中读取数据 * @param url * @return */ public Bitmap getBitmapFromMemory(String url) { return mMemoryCache.get(url); } /** * 将数据写入内存 * @param url * @param bitmap */ public void SetBitmaptoMemory(String url,Bitmap bitmap) { mMemoryCache.put(url, bitmap); } }
package com.example.zhihuibj.utils.bitmap; import android.app.Activity; import android.graphics.Bitmap; import android.widget.ImageView; /* * 自定义图片加载工具 */ public class MyBitMapUtils { private NetCacheUtils mNetCacheUtils; private MyLoaclCacheUtils mLocalCacheUtils; private MemoryCacheUtils mMemoryCacheUtils; public MyBitMapUtils(Activity mActivity) { mLocalCacheUtils= new MyLoaclCacheUtils(); mNetCacheUtils=new NetCacheUtils(mLocalCacheUtils,mMemoryCacheUtils); mMemoryCacheUtils=new MemoryCacheUtils(); } public void display(ImageView ivPic,String url) { //从内存中读取 Bitmap bitmap_memory = mMemoryCacheUtils.getBitmapFromMemory(url); if(bitmap_memory!=null) { ivPic.setImageBitmap(bitmap_memory); System.out.println("从内存读数据啦。。。。"); return; } //从SD卡中读取 Bitmap bitmap = mLocalCacheUtils.GetBitmapFromLoacl(url); if(bitmap!=null) { ivPic.setImageBitmap(bitmap); System.out.println("从本地读数据啦。。。。"); mMemoryCacheUtils.SetBitmaptoMemory(url, bitmap); return; } //从网络中读取 mNetCacheUtils.getBitmapFromNet(ivPic, url); } }