图片三级缓存

首先,我是一个小菜鸟,刚学了到一点东西,虽然很小的一点东西,但我觉得应该记下来,帮助自己也希望帮到他人···
我对三级缓存的理解是,图片首先会在内存中加载,如果内存没有,则请求本地磁盘,有的话会加载到内存中一份,如果没有则请求网络,网络是费时费流量,所以会最后请求,磁盘和内存,内存加载更快,所以首先从内存中加载,所以加载顺序是内存- >磁盘- > 网络!!请求完网络,会在本地磁盘中保存一份,然后内存保存一份
1.创建一个BitmapCacheUtils类:

public class BitmapCacheUtils {

/**
 * 网络缓存工具类
 */
private NetCacheUtils netCacheUtils;
/**
 * 本地缓存工具类
 */
private LocalCacheUtils localCacheUtils;
/**
 * 内存缓存工具类
 */
private MemoryCacheUtils memoryCacheUtils;

public BitmapCacheUtils(Handler handler) {
//首先是内存
    memoryCacheUtils=new MemoryCacheUtils();
    //本地
    localCacheUtils=new LocalCacheUtils(memoryCacheUtils);
    //网络
    netCacheUtils=new NetCacheUtils(handler,localCacheUtils,memoryCacheUtils);
}

/**
 * 三级缓存设计步骤
 * 从内存中取图片,如果没有,则从本地加载
 * 从本地文件中取图片
 * 有的话向内存中保存一份,没有则请求网络
 * 请求网络图片,获取图片,显示在控件上,Handler,position
 * 然后向内存中村一份
 * 向本地文件存一份
 * @param imageUrl
 * @param position
 * @return
 */
public Bitmap getBitmap(String imageUrl, int position) {
    //1.从内存中获取
    if (memoryCacheUtils!=null){
        Bitmap bitmap =memoryCacheUtils.getBitmapFromUrl(imageUrl);
        if (bitmap!=null){
            LogUtil.e("内存加载图片成功=="+position);
            return bitmap;
        }
    }
    //2.从本地中取图片
    if (localCacheUtils!=null){
        Bitmap bitmap =localCacheUtils.getBitmapFromUrl(imageUrl);
        if (bitmap!=null){
            LogUtil.e("本地加载图片成功=="+position);
            return bitmap;
        }
    }
    //3.从网络获取
    netCacheUtils.getBitmapFromNet(imageUrl,position);
    return null;
}

}

2.创建三个类,
//网络缓存

public class NetCacheUtils {

/**
 * 请求图片成功
 */
public static final int SUCCESS =1;
/**
 * 请求图片失败
 */
public static final int FAILURE = 2;
private final Handler handler;
/**
 * 本地缓存工具类
 */
private final LocalCacheUtils localCacheUtils;
/**
 * 内存缓存工具类
 */
private final MemoryCacheUtils memoryCacheUtils;
private ExecutorService service;

public NetCacheUtils(Handler handler, LocalCacheUtils localCacheUtils, MemoryCacheUtils memoryCacheUtils) {
    this.handler=handler;
    this.service=Executors.newFixedThreadPool(10);//创建一个固定大小的线程池,返回一个线程池服务类
    this.localCacheUtils=localCacheUtils;
    this.memoryCacheUtils=memoryCacheUtils;
}

public void getBitmapFromNet(String imageUrl, int position) {
    service.execute(new MyRunnable(imageUrl,position));
}

private class MyRunnable implements Runnable {
    private final String imageUrl;
    private final int position;
    public MyRunnable(String imageUrl, int position) {
        this.imageUrl=imageUrl;
        this.position=position;
    }
    @Override
    public void run() {
        //子线程
        //请求网络图片
        try {
            URL url=new URL(imageUrl);
            HttpURLConnection connection= (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("GET");//只能大写
            connection.setConnectTimeout(5000);
            connection.setReadTimeout(4000);
            connection.connect();//可写可不写
            int code=connection.getResponseCode();
            if (code==200){
                LogUtil.e("请求成功");
                InputStream is=connection.getInputStream();//获取一个输入流
                Bitmap bitmap=BitmapFactory.decodeStream(is);//把输入流转成一个Bitmap对象
                //显示在控件上,发消息把Bitmap发出去和position
                Message msg=Message.obtain();//从队列中取一个空的消息
                msg.what=SUCCESS;//请求图片成功
                msg.arg1=position;
                msg.obj=bitmap;
                handler.sendMessage(msg);
                //然后在内村中缓存一份
                memoryCacheUtils.putBitmap(imageUrl,bitmap);
                //然后在本地缓存一份
                localCacheUtils.putBitmap(imageUrl,bitmap);
            }else {
                LogUtil.e("请求异常,请及时处理");
            }
        } catch (IOException e) {
            e.printStackTrace();
            Message msg=Message.obtain();
            msg.what=FAILURE;
            msg.arg1=position;
            handler.sendMessage(msg);
       	}
   	 }
  }
}

public class LocalCacheUtils {
	private final MemoryCacheUtils memoryCacheUtils;
	public LocalCacheUtils(MemoryCacheUtils memoryCacheUtils) {
    this.memoryCacheUtils=memoryCacheUtils;
}
/**
 * 根据url获取图片
 * @param imageUrl
 * @return
 */
public Bitmap getBitmapFromUrl(String imageUrl) {
    //判断sd卡是否挂载
    if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
        //保存图片在/mnt/sdcard/News
        try {
            String fileName = MD5Encoder.encode(imageUrl);//fnlkajdfjasfjasdf
            File file=new File(Environment.getExternalStorageDirectory()+"/News",fileName);
            if (file.exists()){
                FileInputStream is=new FileInputStream(file);
                Bitmap bitmap=BitmapFactory.decodeStream(is);
                if (bitmap!=null){
                    memoryCacheUtils.putBitmap(imageUrl,bitmap);
                    LogUtil.e("把图片从本地保存到内存中");
                }
                return bitmap;
            }
        } catch (Exception e) {
            e.printStackTrace();
            LogUtil.e("图片获取失败");
        }
    }
    return null;
}

/**
 * 根据url保存图片
 * @param imageUrl url
 * @param bitmap 图片
 */
public void putBitmap(String imageUrl, Bitmap bitmap) {
    //判断sd卡是否挂载
    if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
        //保存图片在/mnt/sdcard/News
        try {
            String fileName = MD5Encoder.encode(imageUrl);//fnlkajdfjasfjasdf
            File file=new File(Environment.getExternalStorageDirectory()+"/News",fileName);
            //本地没有这个目录要先进行创建
            File parentFile =  file.getParentFile();//mnt/sdcard/News
            if(!parentFile.exists()){
                //创建目录
                parentFile.mkdirs();
            }
            if (!file.exists()){
                file.createNewFile();
            }
            //保存图片
            bitmap.compress(Bitmap.CompressFormat.PNG,100, new FileOutputStream(file));
        } catch (Exception e) {
            e.printStackTrace();
            LogUtil.e("图片本地缓存失败");
        	}
    	}
	}
}

public class MemoryCacheUtils {

//集合,装图片的
private LruCache<String,Bitmap> lruCache;
public MemoryCacheUtils() {
    int maxSize= (int) (Runtime.getRuntime().maxMemory()/8);//如果这里写一个1024;
    lruCache=new LruCache<String,Bitmap>(maxSize){
        @Override
        protected int sizeOf(String key, Bitmap value) {
            return value.getRowBytes()*value.getHeight();//这里也要写一个1024;
        }
    };
}

/**
 * 根据url从内存中获取图片
 * @param imageUrl
 * @return
 */
public Bitmap getBitmapFromUrl(String imageUrl) {
    return lruCache.get(imageUrl);
}
/**
 * 根据url保存图片到lruCache集合中
 * @param imageUrl 图片路径
 * @param bitmap 图片
 */
public void putBitmap(String imageUrl, Bitmap bitmap) {
    lruCache.put(imageUrl,bitmap);
	}
}

//实例化图片缓存工具类,这是在要插入的activity中,或者fragment中

private BitmapCacheUtils bitmapCacheUtils;
//创建一个handler,需要发送到BitmapCacheUtils类中
//然后网络请求成功之后,将图片位置等的信息传过来
private Handler handler=new Handler(){
    @Override
    public void handleMessage(Message msg) {
        super.handleMessage(msg);
        switch (msg.what){
            case NetCacheUtils.SUCCESS://图片请求成功
                int position=msg.arg1;
                Bitmap bitmap= (Bitmap) msg.obj;
                LogUtil.e("联网请求图片成功=="+position);
                if (lv_photos_menu.isShown()) {
                    ImageView imageView = (ImageView) lv_photos_menu.findViewWithTag(position);
                    if (imageView != null && bitmap != null) {
                        imageView.setImageBitmap(bitmap);
                    }
                }else if (gv_photos_menu.isShown()){
                    ImageView imageView = (ImageView) gv_photos_menu.findViewWithTag(position);
                    if (imageView != null && bitmap != null) {
                        imageView.setImageBitmap(bitmap);
                    }
                }
                break;
            case NetCacheUtils.FAILURE://图片请求失败
                position=msg.arg1;
                LogUtil.e("联网请求图片成功=="+position);
                break;
        }
    }
};
public InteractMenuDetailPager(Context context, NewsBean.DataEntity dataEntity) {
    super(context);
    this.dataEntity=dataEntity;
    //实例化三级缓存类
    bitmapCacheUtils=new BitmapCacheUtils(handler);
}
//从内存或者本地获取
	Bitmap bitmap=bitmapCacheUtils.getBitmap(imageUrl,position);     
//往适配器中插入数据
    holder.iv_photos_default_menu.setImageBitmap(bitmap);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值