软件编程
位置:首页>> 软件编程>> Android编程>> Android图片 * 缓存开发

Android图片 * 缓存开发

作者:WhatYouSeeMe  发布时间:2023-12-03 22:42:43 

标签: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);
}
}

来源:http://blog.csdn.net/wangjiangjun0815/article/details/77717820

0
投稿

猜你喜欢

手机版 软件编程 asp之家 www.aspxhome.com