Android图片三级缓存开发

因为目前工程无法使用第三方,只能搞一个三级缓存了三级缓存分为内存缓存,本地缓存,网络缓存;缓存的步骤依次是网络,内存,本地,然后取的顺序为内存,本地,网络。在加载图片时引用时尽量采用弱引用避免出现图片过多产生OOM.。

1、内存缓存,android为我们提供LruCache=其中维护着一个LinkedHashMap。LruCache可以用来存储各种类型的数据,我们设置它的大小,一般是系统最大存储空间的1/8.

public class MemoryCacheUtil {

 private LruCache<String, Bitmap> lruCache;

 public MemoryCacheUtil(){
  int maxSize = (int) (Runtime.getRuntime().maxMemory()/8);

  // 一般获取当前应用的最大内存的1/8作为LruCache的容量
  lruCache = new LruCache<String, Bitmap>(maxSize){
   // 设置当前添加的图片的大小
   @Override
   protected int sizeOf(String key, Bitmap value) {
    return value.getRowBytes()*value.getHeight();
   }
  };
 }

 // 从内存缓存取图片
 public Bitmap getBitmap(String url){
  return lruCache.get(url);
 }

 // 在内存缓存存图片
 public void putBitmap(String url,Bitmap bitmap){
  lruCache.put(url, bitmap);
 }
}

2、本地缓存根据url,获取本地文件,把url进行md5加密,作为文件名,保证文件的正确性.

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();
 }
}

本地缓存

public class LocalCacheUtil {

 private String CACHE_URl;
 private MemoryCacheUtil memoryCacheUtil;

 public LocalCacheUtil(MemoryCacheUtil memoryCacheUtil){
  // 初始化本地存储的路径
  CACHE_URl = Environment.getExternalStorageDirectory().getAbsoluteFile()+ "/test";
  this.memoryCacheUtil = memoryCacheUtil;
 }

 // 从本地sdcard取图片
 public Bitmap getBitmap(String url){
  // 根据url,获取本地文件,把url进行md5加密,作为文件名
  try {
   String fileName = MD5Encoder.encode(url);
   File file = new File(CACHE_URl, fileName);
   if(file.exists()){// 判断当前文件是否存在
    // 把当前文件转换成Bitmap对象
    Bitmap bitmap = BitmapFactory.decodeFile(file.getAbsolutePath());
    // 需往内存中存一份
    memoryCacheUtil.putBitmap(url, bitmap);
    return bitmap;
   }

  } catch (Exception e) {
   e.printStackTrace();
  }
  return null;
 }
 // 往本地存图片的方法
 public void saveBitmap(String url,Bitmap bitmap){
  try {
   String fileName = MD5Encoder.encode(url);
   File file = new File(CACHE_URl, fileName);
   // 判断是否需要创建父目录
   File parentFile = file.getParentFile();
   if(!parentFile.exists()){
    parentFile.mkdirs();
   }
   // 把Bitmap对象保存到文件中 质量越高压缩速度越慢
   OutputStream stream = new FileOutputStream(file);
   bitmap.compress(CompressFormat.PNG, 100, stream);//第一个参数可以设置图片格式,第二个图片压缩质量,第三个为图片输出流
  } catch (Exception e) {
   e.printStackTrace();
  }
 }
}

3、网络缓存使用异步加载AsyncTask,使用其有二种原因:

1.doInBackground运行在子线程,做网络请求耗时操作,避免主线程堵塞;

2.onPreExecute和onPostExecute便于更新UI提高用户体验。

public class NetCacheUtil {
 private MemoryCacheUtil memoryCacheUtil;
 private LocalCacheUtil localCacheUtil;
 private ListView lv_image_list;

 public NetCacheUtil(MemoryCacheUtil memoryCacheUtil,LocalCacheUtil localCacheUtil){
  this.memoryCacheUtil = memoryCacheUtil;
  this.localCacheUtil = localCacheUtil;
 }

 public void display(ImageView imageView ,String url, ListView lv_image_list){
   this.lv_image_list = lv_image_list;
  new MyAsyncTask(imageView).execute(new Object[]{url,imageView});
 }
 class MyAsyncTask extends AsyncTask<Object, Void, Bitmap>{
  private ImageView imageView;
  private int position;
  public MyAsyncTask(ImageView imageView2) {
   position = (Integer) imageView2.getTag();
  }

  // 运行在主线程,做准备操作,在doInBackground之前,可以放置加载条提高用户体验
  @Override
  protected void onPreExecute() {
   super.onPreExecute();
  }

  // 运行在子线程,做耗时操作
  @Override
  protected Bitmap doInBackground(Object... params) {
   // 获取url,下载图片
   String url = (String) params[0];
   // 获取ImageView
   imageView = (ImageView) params[1];
   try {
    // 下载图片
    HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
    conn.connect();// 连接网络
    // 获取响应码
    int resCode = conn.getResponseCode();
    if(resCode==200){// 访问成功
     // 把服务器返回的输入流转换成Bitmap对象
     Bitmap bitmap = BitmapFactory.decodeStream(conn.getInputStream());
     // 保存到本地和内存
     memoryCacheUtil.putBitmap(url, bitmap);
     localCacheUtil.saveBitmap(url, bitmap);
     return bitmap;
    }
   } catch (Exception e) {
    e.printStackTrace();
   }
   return null;
  }
  // 运行在主线程,更新界面,在doInBackground之后
  @Override
  protected void onPostExecute(Bitmap result) {
   // 判断线程开始时,那个位置是否还在Listview中
   ImageView view = (ImageView) lv_image_list.findViewWithTag(position);
   if(view!=null){
    view.setImageBitmap(result);
   }
   super.onPostExecute(result);
  }
 }
}

4、封装三级缓存形成ImageUtil,因内存缓存中取速度较快,所以先从内存缓存中取,取不到->本地缓存中取,取不到->网络缓存中取。

public class ImageUtils {

 private MemoryCacheUtil memoryCacheUtil;
 private LocalCacheUtil localCacheUtil;
 private NetCacheUtil netCacheUtil;

 public ImageUtils(){
  memoryCacheUtil = new MemoryCacheUtil();
  localCacheUtil = new LocalCacheUtil(memoryCacheUtil);
  netCacheUtil = new NetCacheUtil(memoryCacheUtil,localCacheUtil);
 }

  public void display(ImageView imageView, String url, ListView lv_photo_list) {
  Bitmap bitmap = null;
  /**
   * 因内存缓存中取速度较快
   * 内存缓存中取,取不到->本地缓存中取,取不到->网络缓存中取
   */
  bitmap = memoryCacheUtil.getBitmap(url);//从内存缓存取图片
  if(bitmap!=null){
   imageView.setImageBitmap(bitmap);
   return;
  }
  bitmap = localCacheUtil.getBitmap(url);//从本地缓存取图片
  if(bitmap!=null){
   imageView.setImageBitmap(bitmap);
   return;
  }
  // 开启线程访问网络,下载图片,并且展示
  netCacheUtil.display(imageView, url,lv_photo_list);
 }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Android图片三级缓存策略(网络、本地、内存缓存)

    一.简介 现在的Android应用程序中,不可避免的都会使用到图片,如果每次加载图片的时候都要从网络重新拉取,这样不但很耗费用户的流量,而且图片加载的也会很慢,用户体验很不好.所以一个应用的图片缓存策略是很重要的.通常情况下,Android应用程序中图片的缓存策略采用"内存-本地-网络"三级缓存策略,首先应用程序访问网络拉取图片,分别将加载的图片保存在本地SD卡中和内存中,当程序再一次需要加载图片的时候,先判断内存中是否有缓存,有则直接从内存中拉取,否则查看本地SD卡中是否有缓存,SD

  • Android中图片的三级缓存机制

    我们不能每次加载图片的时候都让用户从网络上下载,这样不仅浪费流量又会影响用户体验,所以Android中引入了图片的缓存这一操作机制. 原理: 首先根据图片的网络地址在网络上下载图片,将图片先缓存到内存缓存中,缓存到强引用中 也就是LruCache中.如果强引用中空间不足,就会将较早存储的图片对象驱逐到软引用(softReference)中存储,然后将图片缓存到文件(内部存储外部存储)中:读取图片的时候,先读取内存缓存,判断强引用中是否存在图片,如果强引用中存在,则直接读取,如果强引用中不存在,则

  • Android三级缓存原理讲解

    三级缓存 内存缓存 本地缓存(SD卡缓存) 网络缓存 缓存顺序:首先从网络获取图片资源,然后将当前的图片缓存到本地,然后再缓存到内存中,那么下次访问图片资源就会优先从内存获取图片资源,如果内存中没有那么再去本地获取图片资源,如果本地还是没有,那么再从网络获取图片资源. 内存缓存 特点: 访问内存速度最快 不浪费流量 本地缓存 特点: 访问速度中等 不浪费流量 网络缓存 特点: 访问速度慢 浪费流量 网络缓存 网络缓存顾名思义就是从网络获取图片资源,然后来进行显示,那么我们可以通过AsyncTas

  • 详解Android 图片的三级缓存及图片压缩

    为什么需要图片缓存 Android默认给每个应用只分配16M的内存,所以如果加载过多的图片,为了防止内存溢出,应该将图片缓存起来.图片的三级缓存分别是: 内存缓存 本地缓存 网络缓存 其中,内存缓存应优先加载,它速度最快:本地缓存次优先加载,它速度也快:网络缓存不应该优先加载,它走网络,速度慢且耗流量. 三级缓存的具体实现 网络缓存 根据图片的url去加载图片 在本地和内存中缓存 public class NetCacheUtils { private LocalCacheUtils mLoca

  • Android实现图片异步请求加三级缓存

    使用xUtils等框架是很方便,但今天要用代码实现bitmapUtils 的功能,很简单, AsyncTask请求一张图片 ####AsyncTask #####AsyncTask是线程池+handler的封装 第一个泛型: 传参的参数类型类型(和doInBackground一致) 第二个泛型: #####更新进度的参数类型(和onProgressUpdate一致) 第三个泛型: 返回结果的参数类型(和onPostExecute一致, #####和doInBackground返回类型一致) 看A

  • Android中Rxjava实现三级缓存的两种方式

    本文正如标题所说的用rxjava实现数据的三级缓存分别为内存,磁盘,网络,刚好最近在看Android源码设计模式解析与实战(受里面的ImageLoader的设计启发). 我把代码放到了我的hot项目中,github地址 源码下载地址:Rxjava_jb51.rar 1.使用concat()和first()的操作符. 2.使用BehaviorSubject. 先说BehaviorSubject的实现方法,废话不多说直接上代码, /** * Created by wukewei on 16/6/20

  • android中图片的三级缓存cache策略(内存/文件/网络)

    1.简介 现在android应用中不可避免的要使用图片,有些图片是可以变化的,需要每次启动时从网络拉取,这种场景在有广告位的应用以及纯图片应用(比如百度美拍)中比较多. 现在有一个问题:假如每次启动的时候都从网络拉取图片的话,势必会消耗很多流量.在当前的状况下,对于非wifi用户来说,流量还是很贵的,一个很耗流量的应用,其用户数量级肯定要受到影响.当然,我想,向百度美拍这样的应用,必然也有其内部的图片缓存策略.总之,图片缓存是很重要而且是必须的. 2.图片缓存的原理 实现图片缓存也不难,需要有相

  • Android图片三级缓存的原理及其实现

    为什么要使用三级缓存 如今的 Android App 经常会需要网络交互,通过网络获取图片是再正常不过的事了 假如每次启动的时候都从网络拉取图片的话,势必会消耗很多流量.在当前的状况下,对于非wifi用户来说,流量还是很贵的,一个很耗流量的应用,其用户数量级肯定要受到影响 特别是,当我们想要重复浏览一些图片时,如果每一次浏览都需要通过网络获取,流量的浪费可想而知 所以提出三级缓存策略,通过网络.本地.内存三级缓存图片,来减少不必要的网络交互,避免浪费流量 什么是三级缓存 网络缓存, 不优先加载,

  • 浅谈Android 中图片的三级缓存策略

    什么是三级缓存? 内存缓存,优先加载,速度最快 本地缓存,次优先加载,速度快 网络缓存,最后加载,速度慢,浪费流量 为什么要进行三级缓存 三级缓存策略,最实在的意义就是 减少不必要的流量消耗,增加加载速度 . 如今的 APP 网络交互似乎已经必不可少,通过网络获取图片再正常不过了.但是,每次启动应用都要从网络获取图片,或者是想重复浏览一些图片的时候,每次浏览都需要网络获取,消耗的流量就多了,在如今的流量资费来说,肯定会容易影响用户数量. 还有就是网络加载图片,有时候会加载很慢,影响了用户体验.

  • Android使用缓存机制实现文件下载及异步请求图片加三级缓存

    首先给大家介绍Android使用缓存机制实现文件下载 在下载文件或者在线浏览文件时,或者为了保证文件下载的正确性,需要使用缓存机制,常使用SoftReference来实现. SoftReference的特点是它的一个实例保存对一个Java对象的软引用,该软引用的存在不妨碍垃圾收集线程对该Java对象的回收.也就是说,一旦SoftReference保存了对一个Java对象的软引用后,在垃圾线程对这个Java对象回收前,SoftReference类所提供的get()方法返回Java对象的强引用.另外

随机推荐