图片的三级缓存

public class MD5Encoder {
	
	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();
	}
}

一.什么好似三级缓存

  • 1、内存缓存 优先加载,速度最快
  • 2、本地缓存 次优先加载 速度稍快
  • 3、网络缓存 最后加载 速度由网络速度决定(浪费流量)
二.三级缓存的原理:
1.写三个工具类
 内存缓存的工具类
 本地缓存的工具类
 网络缓存的工具类
2.写一个展示图片的工具类对三个工具类进行包装
   1.首先从内存取,如果没有从本地取,本地没有从网络取.
  2.内存缓存的方法是:
android中有一个   LruCache 类专门用来做图片缓存处理的. 它有一个特点,当缓存的图片达到了预先设定的值的时候,那么 近期使用次数最少的图片 就会被回收掉 。首先获取最大内存,然后设置缓存的大小,一般设置为最大内存的1/8之一.
3.本地缓存是储存在sd卡上,通过图片的地址生成Md5,作为文件名.写到文件当中去,之后取的时候通过md5 来判断是否存在.
4.至于网络缓存是从服务器下载图片,下载之后分别写到内存和本地,之后再进行展示.


三代码:
1.内存缓存工具类
/**
 * 内存缓存
 */
public class MemoryCacheUtils {

    /**
     * LinkedHashMap<>(10,0.75f,true);
     * 

* 10是最大致 0.75f是加载因子 true是访问排序 false插入排序 * * */ //private LinkedHashMap mMemoryCache = new LinkedHashMap<>(5,0.75f,true); private LruCache mLruCache; public MemoryCacheUtils() { long maxMemory = Runtime.getRuntime().maxMemory();//最大内存 默认是16兆 运行时候的 mLruCache = new LruCache((int) (maxMemory / 8)) { @Override protected int sizeOf(String key, Bitmap value) { //int byteCount = value.getByteCount(); //得到图片字节数 // @return number of bytes between rows of the native bitmap pixels. int byteCount = value.getRowBytes() * value.getWidth(); return byteCount; } }; } /** * 从内存中读取 * * @param url */ public Bitmap getFromMemroy(String url) { Log.d("MyBitmapUtils", "从内存中加载图片"); return mLruCache.get(url); } /** * 写入到内存中 * * @param url * @param bitmap */ public void setToMemory(String url, Bitmap bitmap) { mLruCache.put(url, bitmap); } }


2.网络缓存
/**
 * 网络缓存工具类
 */
public class NetCacheUtils {


    /**
     * 图片
     */
    private ImageView mImageView;

    /**
     * 图片地址
     */
    private String mUrl;

    /**
     * 本地缓存
     */
    private SDcardCacheUtils mDcardCacheUtils;


    /**
     * 内存缓存
     */
    private MemoryCacheUtils mMemoryCacheUtils;


    public NetCacheUtils(SDcardCacheUtils dcardCacheUtils, MemoryCacheUtils memoryCacheUtils) {
        mDcardCacheUtils = dcardCacheUtils;
        mMemoryCacheUtils = memoryCacheUtils;
    }

    /**
     * 从网络中下载图片
     *
     * @param image
     * @param url
     */
    public void getDataFromNet(ImageView image, String url) {
        new MyAsyncTask().execute(image, url);  //启动Asynctask,传入的参数到对应doInBackground()
    }


    /**
     * 异步下载
     * 

* 第一个泛型 : 参数类型 对应doInBackground() * 第二个泛型 : 更新进度 对应onProgressUpdate() * 第三个泛型 : 返回结果result 对应onPostExecute */ class MyAsyncTask extends AsyncTask { /** * 后台下载 子线程 * * @param params * @return */ @Override protected Bitmap doInBackground(Object... params) { //拿到传入的image mImageView = (ImageView) params[0]; //得到图片的地址 mUrl = (String) params[1]; //将imageview和url绑定,防止错乱 mImageView.setTag(mUrl); Bitmap bitmap = downLoadBitmap(mUrl); return bitmap; } /** * 进度更新 UI线程 * * @param values */ @Override protected void onProgressUpdate(Void... values) { super.onProgressUpdate(values); } /** * 回调结果,耗时方法结束后,主线程 * * @param bitmap */ @Override protected void onPostExecute(Bitmap bitmap) { if (bitmap != null) { //得到图片的tag值 String url = (String) mImageView.getTag(); //确保图片设置给了正确的image if (url.equals(mUrl)) { mImageView.setImageBitmap(bitmap); /** * 当从网络上下载好之后保存到sdcard中 */ mDcardCacheUtils.savaSd(mUrl, bitmap); /** * 写入到内存中 */ mMemoryCacheUtils.setToMemory(mUrl, bitmap); Log.d("MyBitmapUtils", "我是从网络缓存中读取的图片啊"); } } } } /** * 下载图片 * * @param url 下载图片地址 * @return */ private Bitmap downLoadBitmap(String url) { //连接 HttpURLConnection conn = null; try { conn = (HttpURLConnection) new URL(url) .openConnection(); //设置读取超时 conn.setReadTimeout(5000); //设置请求方法 conn.setRequestMethod("GET"); //设置连接超时连接 conn.setConnectTimeout(5000); //连接 conn.connect(); //响应码 int code = conn.getResponseCode(); if (code == 200) { //请求正确的响应码是200 //得到响应流 InputStream inputStream = conn.getInputStream(); //得到bitmap对象 Bitmap bitmap = BitmapFactory.decodeStream(inputStream); return bitmap; } } catch (IOException e) { e.printStackTrace(); } finally { conn.disconnect(); } return null; } }


3.本地缓存
 * 本地缓存
 */
public class SDcardCacheUtils {

    /**
     * 我们读取内存的绝对路径
     */
    public static final String CACHE_PATH = Environment
            .getExternalStorageDirectory().getAbsolutePath() + "/aixuexi";

    /**
     * 从本地读取
     * @param url
     */
    public Bitmap getFromSd(String url){
        String fileName = null;
        try {
            //得到图片的url的md5的文件名
            fileName = MD5Encoder.encode(url);
        } catch (Exception e) {
            e.printStackTrace();
        }
        File file = new File(CACHE_PATH,fileName);

        //如果存在,就通过bitmap工厂,返回的bitmap,然后返回bitmap
        if (file.exists()){
            try {
                Bitmap bitmap = BitmapFactory.decodeStream(new FileInputStream(file));
                Log.d("MyBitmapUtils", "从本地读取图片啊");
                return bitmap;
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    /**
     * 向本地缓存
     *
     * @param url   图片地址
     * @param bitmap   图片
     */
    public void savaSd(String url,Bitmap bitmap){
        String fileName = null;
        try {
            //我们对图片的地址进行MD5加密,作为文件名
            fileName = MD5Encoder.encode(url);
        } catch (Exception e) {
            e.printStackTrace();
        }

        /**
         * 以CACHE_PATH为文件夹  fileName为文件名
         */
        File file = new File(CACHE_PATH,fileName);

        //我们首先得到他的符文剑
        File parentFile = file.getParentFile();
        //查看是否存在,如果不存在就创建
        if (!parentFile.exists()){
            parentFile.mkdirs(); //创建文件夹
        }

        try {
            //将图片保存到本地
            /**
             * @param format   The format of the compressed image   图片的保存格式
             * @param quality  Hint to the compressor, 0-100. 0 meaning compress for
             *                 small size, 100 meaning compress for max quality. Some
             *                 formats, like PNG which is lossless, will ignore the
             *                 quality setting
             *                 图片的保存的质量    100最好
             * @param stream   The outputstream to write the compressed data.
             */
            bitmap.compress(Bitmap.CompressFormat.JPEG,100,new FileOutputStream(file));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }
}

4.md5
public class MD5Encoder {
	
	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();
	}
}

5.图片加载工具类
import android.graphics.Bitmap;
import android.widget.ImageView;

/**
 * 自定义的bitmap工具类
 */
public class MyBitmapUtils {


    /**
     * 网络缓存
     */
    public NetCacheUtils mNetCacheUtils;

    /**
     * 本地缓存
     */
    public SDcardCacheUtils mSdCacheUtils;

    /**
     * 内存缓存
     */
    public MemoryCacheUtils mMemoryCacheUtils;


    public MyBitmapUtils() {
        mSdCacheUtils = new SDcardCacheUtils();
        mMemoryCacheUtils = new MemoryCacheUtils();
        mNetCacheUtils = new NetCacheUtils(mSdCacheUtils, mMemoryCacheUtils);
    }

    /**
     * 展示图片的方法
     *
     * @param image
     * @param url
     */
    public void display(ImageView image, String url) {


        //从内存中读取
        Bitmap fromMemroy = mMemoryCacheUtils.getFromMemroy(url);
        //如果内存中有的h话就直接返回,从内存中读取
        if (fromMemroy != null) {
            image.setImageBitmap(fromMemroy);

            return;
        }


        //从本地SD卡读取
        Bitmap fromSd = mSdCacheUtils.getFromSd(url);
        if (fromSd != null) {
            image.setImageBitmap(fromSd);

            mMemoryCacheUtils.setToMemory(url, fromSd);

            return;
        }
        //从网络中读取
        mNetCacheUtils.getDataFromNet(image, url);

    }
}




参考:
https://github.com/wuyinlei/MyBitmapUtils
http://blog.chinaunix.net/uid-26930580-id-4138306.html
http://www.cnblogs.com/snake-hand/archive/2013/06/08/3127558.html
http://blog.csdn.net/xyz_lmn/article/details/12746581 


你可能感兴趣的:(android,网络编程)