android图片的三级缓存


一、图片的三级缓存
1. 内存
    1. 内存的引用
        1. 强引用
            特点:没有变量引用 ,就会被垃圾回收线程收到,直到程序崩溃,也不会回收
        2. 软引用
            特点:垃圾回收线程执行,不一定会回收,内存不足的时候,崩溃之前,清理软引用
        3. 弱引用
            特点:垃圾回收线程一跑,就被回收
        4. 虚引用
            特点:垃圾回收一跑也被清理,该应用获取的数据都为null

     2. 针对android系统
         1.  LruCache
               内存不足时,回收该容器中的数据
2. 本地(硬盘)
       文件:
              sdcard

              app(/data/data/包名/cache)

              sharedpreferences
3. 网络
        网络读取 

二、使用操作

    1. 先从内存取
    2. 再从本地文件中
    3. 从网络取

三、加载网络图片错位
1. 标记

四、代码


public class BitmapCacheUtils
{

    //动态获取jvm的内存

    private int maxSize = (int) (Runtime.getRuntime().freeMemory() / 2);
    //图片的缓存容器
    private LruCache<String, Bitmap> memCache = new LruCache<String, Bitmap>(maxSize) {

        @Override
        protected int sizeOf(String key, Bitmap value) {
            // TODO Auto-generated method stub
            return value.getRowBytes() * value.getHeight();
        }

    };
    //保留最后一次访问url的信息
    private Map<ImageView,String> urlImageViewDatas = new HashMap<ImageView, String>();




    private File cacheDir ;
    private MainActivity mainActivity;
    private ExecutorService    threadPool;

    public BitmapCacheUtils(MainActivity mainActivity) {
        this.mainActivity = mainActivity;
        //获取当前app的cache目录
        cacheDir = mainActivity.getCacheDir();
        //线程池
        threadPool = Executors.newFixedThreadPool(6);
    }
    public void display(ImageView iv, String ivUrl) {
       <span style="color:#FF0000;"> // 1. 先从内存取</span>

        Bitmap bitmap = memCache.get(ivUrl);
        if (bitmap != null) {
            System.out.println("从内存获取数据");
            //缓存中有图片
            iv.setImageBitmap(bitmap);
            return;
        }

       <span style="color:#FF0000;"> // 2. 再从本地文件中, app(/data/data/包名/cache)</span>
        bitmap = getCacheFile(ivUrl);
        if (bitmap != null) {
            System.out.println("从文件获取数据");
            //本地文件中有图片
            iv.setImageBitmap(bitmap);
            return;
        }

       <span style="color:#FF0000;"> // 3. 从网络取</span>
        urlImageViewDatas.put(iv, ivUrl);//保留最后一次访问的url
        getBitmapFromNet(iv, ivUrl);
    }

    private void getBitmapFromNet(ImageView iv, String ivUrl) {
        //new Thread(new DownLoadUrl(iv, ivUrl)).start();
        //线程池
        threadPool.submit(new DownLoadUrl(iv, ivUrl));
    }

    private class DownLoadUrl implements Runnable{
        private String ivUrl;
        private ImageView iv;
        public DownLoadUrl(ImageView iv,String ivUrl){
            this.iv = iv;
            this.ivUrl = ivUrl;
        }
        @Override
        public void run() {
            //访问网络 
            try {
                URL url = new URL(ivUrl);
                HttpURLConnection con = (HttpURLConnection) url.openConnection();
                con.setConnectTimeout(6000);//设置超时时间
                con.setRequestMethod("GET");
                int code = con.getResponseCode();
                if (code == 200) {
                    //请求成功
                    InputStream inputStream = con.getInputStream();
                    final Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
                    //1.往内存中添加
                    memCache.put(ivUrl, bitmap);

                    //2.往本地文件中添加
                    saveBitmapToCacheFile(bitmap,ivUrl);

                    //3.显示数据
                    mainActivity.runOnUiThread(new Runnable() {

                        @Override
                        public void run() {
                            System.out.println("从网络获取数据");

                            // 显示图片
                            // 判断url是不是最新的
                            //是最新的 自己的数据
                            if (ivUrl.equals(urlImageViewDatas.get(iv))) {
                                //自己的数据
                                iv.setImageBitmap(bitmap);
                            }
                        }
                    });

                }

            } catch (MalformedURLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

        }

    }

    /**
     * 保存bitmap到cache目录的文件中
     * @param bitmap
     * @param ivUrl
     */
    public void saveBitmapToCacheFile(Bitmap bitmap,String ivUrl) {
        File file = new File(cacheDir,Md5Utils.md5(ivUrl));
        try {
            bitmap.compress(CompressFormat.JPEG, 100, new FileOutputStream(file));
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    /**
     * @param ivUrl
     *     当做缓存图片的名字
     * @return
     */
    public Bitmap getCacheFile(String ivUrl){
        //把ivUrl转换MD5值,再把md5 做文件名
        File file = new File(cacheDir,Md5Utils.md5(ivUrl));
        if (file != null  && file.exists()) {
            //文件存在
            //把文件转换成bitmap
            Bitmap bitmap = BitmapFactory.decodeFile(file.getAbsolutePath());

            //再往内存写
            memCache.put(ivUrl, bitmap);
            return bitmap;
        } else {
            //不存在
            return null;
        }

    }

}

五、MD5工具类<pre name="code" class="java">public class Md5Utils {
	
	/**
	 * @param path
	 *    ?????·??
	 * @return
	 *    ?????MD5?
	 */
	public static String getFileMD5(String path){
		StringBuilder mess = new StringBuilder();
		try {
			FileInputStream fis = new FileInputStream(new File(path));
			//???MD5??????
			MessageDigest md = MessageDigest.getInstance("MD5");
			byte[] buffer = new byte[10240];
			int len = fis.read(buffer);
			while (len != -1) {
				md.update(buffer, 0, len);
				//??????
				len = fis.read(buffer);
			}
			byte[] digest = md.digest();
			for (byte b : digest){
				//???????????16??????  
				int d = b & 0xff;// 0x000000ff
				String hexString = Integer.toHexString(d);
				if (hexString.length() == 1) {//?????4λ?0
					hexString = "0" + hexString;
				}
				hexString = hexString.toUpperCase();
				mess.append(hexString);//????????????2λ??????????????????
				
			}
		} catch (NoSuchAlgorithmException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return mess + "";
	}
	public static String md5(String str){
		StringBuilder mess = new StringBuilder();
		try {
			//???MD5??????
			MessageDigest md = MessageDigest.getInstance("MD5");
			byte[] bytes = str.getBytes();
			byte[] digest = md.digest(bytes);
			
			for (byte b : digest){
				//???????????16??????  
				int d = b & 0xff;// 0x000000ff
				String hexString = Integer.toHexString(d);
				if (hexString.length() == 1) {//?????4λ?0
					hexString = "0" + hexString;
				}
				mess.append(hexString);//????????????2λ??????????????????
				
			}
		} catch (NoSuchAlgorithmException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return mess + "";
	}
}


 
 


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值