当前位置: 首页 > 编程笔记 >

Android图片三级缓存开发

白修谨
2023-03-14
本文向大家介绍Android图片三级缓存开发,包括了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);
 }
}

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

 类似资料:
  • 本文向大家介绍Android中图片的三级缓存机制,包括了Android中图片的三级缓存机制的使用技巧和注意事项,需要的朋友参考一下 我们不能每次加载图片的时候都让用户从网络上下载,这样不仅浪费流量又会影响用户体验,所以Android中引入了图片的缓存这一操作机制。 原理:   首先根据图片的网络地址在网络上下载图片,将图片先缓存到内存缓存中,缓存到强引用中 也就是LruCache中。如果强引用中空

  • 本文向大家介绍Android图片三级缓存策略(网络、本地、内存缓存),包括了Android图片三级缓存策略(网络、本地、内存缓存)的使用技巧和注意事项,需要的朋友参考一下 一、简介 现在的Android应用程序中,不可避免的都会使用到图片,如果每次加载图片的时候都要从网络重新拉取,这样不但很耗费用户的流量,而且图片加载的也会很慢,用户体验很不好。所以一个应用的图片缓存策略是很重要的。通常情况下,A

  • 本文向大家介绍Android 三级缓存?相关面试题,主要包含被问及Android 三级缓存?时的应答技巧和注意事项,需要的朋友参考一下 网络加载,不优先加载,速度慢,浪费流量 本地缓存,次优先加载,速度快 内存缓存,优先加载,速度最快 首次加载Android App时,肯定要通过网络交互来获取图片,之后我们可以将图片保存至本地SD卡和内存中,之后运行APP时,优先访问内存中的图片缓存,若内存中没有

  • 本文向大家介绍Android 图片的三级缓存机制实例分析,包括了Android 图片的三级缓存机制实例分析的使用技巧和注意事项,需要的朋友参考一下 Android 图片的三级缓存机制实例分析 当我们获取图片的时候,如果不加以协调好图片的缓存,就会造成大流量,费流量应用,用户体验不好,影响后期发展。为此,我特地分享Android图片的三级缓存机制之从网络中获取图片,来优化应用,具体分三步进行: (1

  • 本文向大家介绍Android实现图片异步请求加三级缓存,包括了Android实现图片异步请求加三级缓存的使用技巧和注意事项,需要的朋友参考一下 使用xUtils等框架是很方便,但今天要用代码实现bitmapUtils 的功能,很简单, AsyncTask请求一张图片 ####AsyncTask #####AsyncTask是线程池+handler的封装 第一个泛型: 传参的参数类型类型(和doIn

  • 本文向大家介绍详解Android中图片的三级缓存及实例,包括了详解Android中图片的三级缓存及实例的使用技巧和注意事项,需要的朋友参考一下 详解Android中图片的三级缓存及实例 为什么要使用三级缓存 如今的 Android App 经常会需要网络交互,通过网络获取图片是再正常不过的事了 假如每次启动的时候都从网络拉取图片的话,势必会消耗很多流量。在当前的状况下,对于非wifi用户来说,流量