使用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