使用LruCache和DiskLruCache实现ListView双缓存
来源:互联网 发布:软件分析师考试 编辑:程序博客网 时间:2024/06/05 04:22
package com.example.listviewcache;import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.File;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.URL;import java.security.MessageDigest;import java.security.NoSuchAlgorithmException;import java.util.HashSet;import java.util.Set;import libcore.io.DiskLruCache;import libcore.io.DiskLruCache.Editor;import libcore.io.DiskLruCache.Snapshot;import android.content.Context;import android.content.pm.PackageManager.NameNotFoundException;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.os.AsyncTask;import android.os.Environment;import android.support.v4.util.LruCache;import android.util.Log;import android.widget.ImageView;import android.widget.ListView;public class ImageLoader { /** * URL字符串数组 */ private String[] imageUrls; /** * LruCache 内存缓存 */ private LruCache<String, Bitmap> mMemCache; /** * DiskLruCache 外存(SD)缓存 */ private DiskLruCache mDiskCache; /** * ListView 对象 */ private ListView mLv; private Context mContext; private final static String tag = "ImageLoader"; private Set<DownloadTask> mTaskPool; // 程序内存1/8作为内存缓存 private final static int MEMORYCACHE_MAXSIZE = (int) (Runtime.getRuntime() .maxMemory() / 8); private final static int DISKORYCACHE_MAXSIZE = 1024 * 1024 * 8; // 8MB /** * construtor * @param context * @param imageUrl URL 字符串數組 * @param lv ListView 对象 */ public ImageLoader(Context context, String[] imageUrl, ListView lv) { super(); Log.w(tag, "Constructor"); this.mContext = context; this.mLv = lv; this.imageUrls = imageUrl; this.mTaskPool = new HashSet<ImageLoader.DownloadTask>(); this.mMemCache = new LruCache<String, Bitmap>(MEMORYCACHE_MAXSIZE) { @Override protected int sizeOf(String key, Bitmap value) { return value.getByteCount(); } }; this.mLv = lv; String dirName = "ImageCache"; int version = getAppVersion(); try { mDiskCache = DiskLruCache.open(getCacheDir(dirName), version, 1, DISKORYCACHE_MAXSIZE); } catch (IOException e) { e.printStackTrace(); } } /** * 获得缓存路径 * * @param fileName * 文件名 * @return 返回文件的绝对全路径 */ public File getCacheDir(String fileName) { String cachePath; if (Environment.MEDIA_MOUNTED.equals(Environment .getExternalStorageState()) || !Environment.isExternalStorageRemovable()) { cachePath = mContext.getExternalCacheDir().getPath(); } else { cachePath = mContext.getCacheDir().getPath(); } File absFile = new File(cachePath + File.separator + fileName); Log.w(tag, "getCacheDir:"+absFile.toString()); return absFile; } /** * 获得App版本号 */ public int getAppVersion() { Log.w(tag, "getAppVersion"); try { int version = mContext.getPackageManager().getPackageInfo( mContext.getPackageName(), 0).versionCode; } catch (NameNotFoundException e) { e.printStackTrace(); } return 1; } /** * 将Bitmap 对象存入内存缓存中 * @param urlStr * @param bitmap */ public void putInMem(String urlStr, Bitmap bitmap) { Log.w(tag, "putInMem"); if (mMemCache.get(urlStr) == null) { mMemCache.put(urlStr, bitmap); } } /** * 通过URL字符串从内存中查找 * @param urlStr * @return 如果找到,返回,否则,返回NULL */ public Bitmap getFromMemCache(String urlStr) { Log.w(tag, "getFomMem"); Bitmap bitmap = mMemCache.get(urlStr); if (bitmap != null) { return bitmap; } else return null; } /** * 这个方法效率很低,有待改进 * @param urlStr URL 字符串 * @param bitmap URL字符串对应的Bitmap 对象 * @throws Exception */ public void putInDisk(String urlStr, Bitmap bitmap) throws Exception { Log.w(tag, "putInDisk"); // 存入 内存缓存 long tick = System.currentTimeMillis(); String key = hashKeyForDisk(urlStr); Editor editor = mDiskCache.edit(key); if (editor != null) { OutputStream os = editor.newOutputStream(0); ByteArrayOutputStream baos = new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos); InputStream in = new ByteArrayInputStream(baos.toByteArray()); int len; byte[] buffer = new byte[2048]; while ((len = in.read(buffer)) != -1) { os.write(buffer, 0 ,len); } os.close(); in.close(); editor.commit(); long tock = System.currentTimeMillis(); Log.w(tag, "time "+(tock-tick)); } } /** * 将Bitmap 对象存入外存(SD)缓存 * @param urlStr URL 字符串 * @param in 输入流,从中读取Bitmap * @throws Exception */ public void putInDiskStream(String urlStr, InputStream in) throws Exception { Log.w(tag, "putInDisk"); // 存入 内存缓存 long tick = System.currentTimeMillis(); String key = hashKeyForDisk(urlStr); Editor editor = mDiskCache.edit(key); if (editor != null) { OutputStream os = editor.newOutputStream(0); int len; byte[] buffer = new byte[2048]; while ((len = in.read(buffer)) != -1) { os.write(buffer, 0 ,len); } os.close(); in.close(); editor.commit(); long tock = System.currentTimeMillis(); Log.w(tag, "time "+(tock-tick)); } } /** * 从外存(SD)根据URL 字符串查找 * @param urlStr * @return 如果找到,返回Bitmap对象,否则,返回NULL * @throws Exception */ public Bitmap getFromDiskCache(String urlStr) throws Exception { Log.w(tag, "getFromDisk"); // 从内存读取,首先读取到的事快照 String key = hashKeyForDisk(urlStr); Snapshot snapShot = mDiskCache.get(key); if (snapShot == null) { return null; } // 从外存读取,并存入内存缓存 snapShot = mDiskCache.get(key); InputStream is = snapShot.getInputStream(0); Bitmap bitmap = BitmapFactory.decodeStream(is); if (bitmap != null) { Log.w(tag, "Disk Fikd OK"); } return bitmap; } /** * 将byte数组转成16进制字符串 * * @param digest * @return */ private String bytesToHexString(byte[] digest) { Log.w(tag, "bytesToHex"); String hex; StringBuffer sb = new StringBuffer(); for (int i = 0; i < digest.length; i++) { hex = Integer.toHexString(0xff & digest[i]); if (hex.length() == 1) { sb.append('0'); } sb.append(hex); } return sb.toString(); } /** * 将URL字符串编码MD5 * * @param urlStr * @return */ private String hashKeyForDisk(String urlStr) { Log.w(tag, "hashKeyForDisk"); String cacheStr; try { MessageDigest md = MessageDigest.getInstance("MD5"); md.update(urlStr.getBytes()); cacheStr = bytesToHexString(md.digest()); } catch (NoSuchAlgorithmException e) { cacheStr = String.valueOf(urlStr.hashCode()); e.printStackTrace(); } return cacheStr; } /** * 根据URL从网络下载图片 * @param urlStr URL 字符串 * @return 成功则返回Bitmap 对象,否则返回NULL */ private Bitmap getBitmapFromUrl(String urlStr) { long tick = System.currentTimeMillis(); Log.w(tag, "getBitmapFromUrl"); URL url; Bitmap bitmap = null; try { url = new URL(urlStr); bitmap = BitmapFactory.decodeStream(url.openStream()); } catch (Exception e) { Log.w(tag, "下载图片异常:"+e.getMessage()); e.printStackTrace(); } long tock = System.currentTimeMillis(); Log.w(tag, "time2 "+(tock - tick)); return bitmap; } /** * 通过URL设置ImageView * @param iv ListView 对象,ImageView 的容器 * @param urlStr URL 字符串 */ public void setImageView(ImageView iv, String urlStr) { Log.w(tag, "setImageView"); Bitmap bitmap = null; try { bitmap = fetchImage(urlStr); if (iv.getTag().equals(urlStr)) { iv.setImageBitmap(bitmap); } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * 获得Bitmap对象后,将其设置给URL对象的ImageView, * 通过findViewWithTag找到URL对应的ImageView * @param urlStr * @param bitmap */ private void setImageViewBitmap(String urlStr, Bitmap bitmap) { Log.w(tag, "setImageViewBitmap"); ImageView iv = (ImageView) mLv.findViewWithTag(urlStr); if (iv != null) { Log.w(tag, "----find iv----"); iv.setImageBitmap(bitmap); } } /** * 对外调用,获取图片,先查找内存,然后外存,然后网络 * 如果从外存找到,则存入内存 * 如果从网络找到,则存入内存和外存 * @param urlStr * @return * @throws Exception */ public Bitmap fetchImage(String urlStr) throws Exception { Log.w(tag, "fetchImage"); //查找内存缓存,找到则返回 Bitmap bitmap = getFromMemCache(urlStr); if (bitmap != null) { return bitmap; } //查找外存(SD)缓存,找到则返回 bitmap = getFromDiskCache(urlStr); if (bitmap != null) { putInMem(urlStr, bitmap); return bitmap; } //从网上下载,如果成功,则在onPostExecute() 中直接为ImageView设置Bitmap DownloadTask task = new DownloadTask(); mTaskPool.add(task); task.execute(urlStr); return null; } /** * 异步任务类下载图片 * @author zhouweixian * */ public class DownloadTask extends AsyncTask<String, Void, Bitmap> { Bitmap bitmap; String urlStr; @Override protected Bitmap doInBackground(String... params) { Log.w(tag, "doInBackground"); urlStr = params[0]; if(isCancelled()) return null; bitmap = getBitmapFromUrl(params[0]); return bitmap; } @Override protected void onPostExecute(Bitmap result) { Log.w(tag, "onPostExecute"); //下载成功,设置ImageView setImageViewBitmap(urlStr, result); try { //存入缓存 putInMem(urlStr, result); putInDisk(urlStr, result); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } //任务完成,移除 mTaskPool.remove(this); super.onPostExecute(result); } } /** * 取消所有任务 */ public void cacelAllTasks() { Log.w(tag, "cacelAllTasks"); for (DownloadTask task : mTaskPool) { task.cancel(false); } } /** * 刷新DiskLruCache缓存 */ public void flush() { Log.w(tag, "flush"); try { if (mDiskCache != null) { mDiskCache.flush(); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } }}
0 0
- 使用LruCache和DiskLruCache实现ListView双缓存
- 使用LruCache和DiskLruCache实现ListView双缓存
- 使用LruCache和DiskLruCache实现内存磁盘二级图片缓存
- 使用lrucache和diskLrucache实现照片墙
- Android使用LruCache、DiskLruCache实现图片缓存+图片瀑布流
- 利用LruCache和DiskLruCache使用图片加载的三级缓存
- 图片的LruCache缓存和DiskLruCache缓存
- 【LruCache和DiskLruCache结合】图片缓存机制
- 【LruCache和DiskLruCache结合】图片缓存机制
- Android的缓存技术:LruCache和DiskLruCache
- Android的缓存策略:LruCache和DiskLruCache
- Android 缓存策略LruCache和DiskLruCache学习
- Andoird LruCache和DiskLruCache缓存详解
- 图片缓存-LruCache、DiskLruCache
- Android缓存机制Lrucache内存缓存和DiskLruCache磁盘缓存
- 使用LruCache和DiskLruCache来下载图片
- android网络相册(带磁盘缓存DiskLruCache 和内存缓存LruCache)
- Fragment中存放GridView,结合LruCache、DiskLruCache和HttpURLConnection实现图片下载、缓存
- sql语句写法示例--mysql
- matlab批量读取文件的两种方法
- Firefox49.0中插件Vimperator自动补全功能失效
- bzoj4516: [Sdoi2016]生成魔咒
- hololens 开发者 建议
- 使用LruCache和DiskLruCache实现ListView双缓存
- codeforces 716 B. Anatoly and Cockroaches(greedy)
- 【专题三】第三弹!全球首个微信应用号开发教程!通宵吐血赶稿,每日更新!
- 本地运行spark设置日志级别的2种方式
- Android实现ListView异步加载图片
- 数据库知识点1
- 【Linux】Linux下安装Tomcat服务器
- Hibernate问题1
- 各种二叉树的判断转化(leetcode 、pat)