图片的三级缓存

三级缓存:
强引用---》软引用---》sdCard


HashMap<String,Bitmap> map = new HashMap<String,Bitmap>();//存储图片的"数据库"
new 出来的内存空间 强引用


内存:强引用   软引用     弱引用 虚引用
1、强引用:new LruCache
垃圾回收机制--》这块空间是无法回收。java当内存不足的时候宁可抛出OutofMemory  Error
也不会回收这部分空间。
2、软引用:softReference
一般情况下不会回收这部分空间,除非内存不足了才会回收。
3、弱引用 weakReference
只要垃圾回收器扫描到了这块空间就会回收。不管内存是否充足,而且长时间不使用了就会回收
4、虚引用:
形同虚设。

三级缓存好处:
1、减少服务器压力
2、提高客户加载图片的速度
3、减少了内存溢出
4、实现了离线功能


存: 第一次加载数据
使用异步任务下载图片,先采用LruCache保存图片,如果LruCache存储满了则将数据驱逐到软引用中,
同时还会将数据保存到sdCard中

取: 以后加载数据
  判断LruCache中是否存在需要的图片,如果不存在去软引用中获取,如果软引用中存在则将软引用中的图片取出来放到LruCache中一份,

  如果没有则去sdCard中查找,如果sdCard有图片就从sdCard读取,如果sdCard中也没有就从网络下载

以上就是三级缓存的介绍,下面我们看一下具体的代码实现:

package com.example.text06;

import java.lang.ref.SoftReference;
import java.util.LinkedHashMap;

import com.example.utils.ExternalStroageUtil;
import com.example.utils.HttpUtil;

import android.os.AsyncTask;
import android.os.Bundle;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Log;
import android.util.LruCache;
import android.view.View;
import android.widget.ImageView;

public class MainActivity extends Activity {

	private ImageView iv;
	private LinkedHashMap<String, SoftReference<Bitmap>> map = new LinkedHashMap<String, SoftReference<Bitmap>>();
	private MyLruCache lruCache;
	private String PATH = "https://www.baidu.com/img/bd_logo1.png";

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		iv = (ImageView) findViewById(R.id.iv);
		// 获取虚拟机能够分配的最大内存
		int maxMemory = (int) Runtime.getRuntime().maxMemory();
		Log.i("main", "最大内存为:" + maxMemory);
		int memory = maxMemory / 8;
		// 将memory设置给强引用
		lruCache = new MyLruCache(memory);
	}
	
	public void download(View view) {
		//取数据
		Bitmap bitmap = getCacheBitmap();
		//判断bitmap
		if (bitmap != null) {
			iv.setImageBitmap(bitmap);
		}else{
			//网络加载数据
			new MyTask().execute(PATH);
		}
	}
	/**
	 * 从内存读取图片
	 * @return
	 */
	private Bitmap getCacheBitmap() {
		Bitmap bitmap = null;
		//1、去强引用中获取图片
		bitmap = lruCache.get(PATH);
		if (bitmap != null) {
			Log.i("main", "从强引用中获取图片");
		}else{
			//3、从软引用中获取图片
			SoftReference<Bitmap> reference = map.get(PATH);
			if (reference != null) {
				//说明软引用中有图片
				bitmap = reference.get();
				//向强引用中加入图片
				lruCache.put(PATH, bitmap);
				//从软引用中移除
				map.remove(PATH);
				Log.i("main", "从软引用中获取图片");
			}else{
				//去sdCard获取图片
				byte[] data = ExternalStroageUtil.readExternalStorageRoot("info.png");
				if (data != null && data.length != 0) {
					bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
					Log.i("main", "从sdCard中获取图片");
					lruCache.put(PATH, bitmap);
					Log.i("main", "图片存入强引用成功");
				}
			}
		}
		return bitmap;
	}
	/**
	 * 创建一个异步任务类
	 */
	class MyTask extends AsyncTask<String, Void, Bitmap>{
		@Override
		protected Bitmap doInBackground(String... params) {
			Bitmap bitmap = null;
			byte[] data = HttpUtil.getHttpResult(params[0], MainActivity.this);
			if (data != null && data.length != 0) {
				bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
				//存入强引用中一份
				lruCache.put(params[0], bitmap);
				//写入sdCard
				boolean flag = ExternalStroageUtil.writeExternalStorageRoot("info.png", data);
				if (flag) {
					Log.i("main", "图片存入sdCard成功");
				}else{
					Log.i("main", "图片存入sdCard失败");
				}
			}else{
				Log.i("main", "网络获取失败!");
			}
			return bitmap;
		}
		@Override
		protected void onPostExecute(Bitmap result) {
			
			super.onPostExecute(result);
			//设置给ImageView
			iv.setImageBitmap(result);
		}
	}
	/**
	 * 定义一个用于保存多张图片的强引用
	 * 
	 * @author Administrator
	 * 
	 */
	public class MyLruCache extends LruCache<String, Bitmap> {

		public MyLruCache(int maxSize) {
			super(maxSize);

		}
		
		@Override
		/**
		 * 主要用于计算图片的大小
		 * 通过value值进行计算
		 */
		protected int sizeOf(String key, Bitmap value) {
			
			int size = value.getRowBytes() * value.getHeight();
			return super.sizeOf(key, value);
		}
		@Override
		/**
		 * 当LruCache满了需要驱逐出去一些数据回调此方法
		 * 参数:
		 * 	boolean evicted:当驱逐数据的时候则将该值置为true;
		 * String key:用来唯一标示这张图片的
		 * Bitmap oldValue:驱逐出去的图片
		 * Bitmap newValue:新进来的图片
		 */
		protected void entryRemoved(boolean evicted, String key,
				Bitmap oldValue, Bitmap newValue) {
			
			super.entryRemoved(evicted, key, oldValue, newValue);
			if (evicted) {
				//将数据存放到软引用中
				SoftReference<Bitmap>bitmapReference = new SoftReference<Bitmap>(oldValue);
				//将软引用加入到Map集合中
				map.put(key, bitmapReference);
				
			}
		}
	}

}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值