首页 > 系统 > Android > 正文

Android图片三级缓存开发

2019-10-22 18:16:31
字体:
来源:转载
供稿:网友

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

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


注:相关教程知识阅读请移步到Android开发频道。
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表