Android DiskLruCache 硬盘缓存案例

文章来源:http://blog.csdn.net/guolin_blog/article/details/28863651

DisKLruCache是Google提供的一套硬盘缓存的解决方案(非Google官方编写,但是已获得官方认证)

存储地址

外部存储:/sdcard/Android/data/.../cache

手机存储:Android/data/.../cache

下载DiskLruCache

DiskLruCache类并不在Android API中,所以需要下载,DiskLruCache的源码可以在Google下载

android.googlesource.com/platform/libcore/+/jb-mr2-release/luni/src/main/java/libcore/io/DiskLruCache.java

下载后会有很多导入包的问题,本人能力有限没有去解决,可以在git上下载或引入大神处理好的DiskLruCache.java类

https://github.com/JakeWharton/DiskLruCache

implementation 'com.jakewharton:disklrucache:2.0.2'

打开硬盘缓存

DiskLruCache的实例不是new出来的,需要调用open()方法

open(File directory, int appVersion, int valueCount, long maxSize)

接收的参数,directory指定的缓存地址,appVersion指定当前应用程序的版本号,valueCount指定同一个key对应多少个缓存文件,基本都是传1,maxSize指定可以缓存多少个字节的数据。

DiskLruCache diskLruCache = null;

public void open(Context context){
try {
        
        File cacheFile = getDiskCacheDir(context, "bitmap");
        //exists方法来检测文件是否存在
        if (!cacheFile.exists()){
            //mkdir() 如果你想在已经存在的文件夹(D盘下的yyy文件夹)下建立新的文件夹(2010-02-28文件夹),就可以用此方法。此方法不能在不存在的文件夹下建立新的文件夹。假如想建立名字是”2010-02-28”文件夹,那么它的父文件夹必须存在。
            //
            //mkdirs() 如果你想根据File里的路径名建立文件夹(当你不知道此文件夹是否存在,也不知道父文件夹存在),就可用此方法,它建立文件夹的原则是:如果父文件夹不存在并且最后一级子文件夹不存在,它就自动新建所有路经里写的文件夹;如果父文件夹存在,它就直接在已经存在的父文件夹下新建子文件夹。
            cacheFile.mkdirs();
        }

            diskLruCache= DiskLruCache.open(cacheFile,getVersionId(context),1,10*1024*1024);
        } catch (IOException e) {
            e.printStackTrace();
        }
}

获取文件的缓存地址

 public File getDiskCacheDir(Context context,String uniqueName){
        String cachePath;
        //Environment包含了对SD卡操作的的类,以及常亮状态,获取外部存储目录
        if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())||Environment.isExternalStorageRemovable()){
            //获取应用程序在外部存储的存储目录
            cachePath = context.getExternalCacheDir().getPath();

        }else{
            //获取应用程序自己的缓存目录
            cachePath = context.getCacheDir().getPath();
        }

        return new File(cachePath + File.separator+uniqueName);
    }

 

获取应用程序版本号

public int getVersionId(Context context){
        try {
            PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
            return packageInfo.versionCode;
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }
        return 1;
    }

写入硬盘缓存

图片地址为 https://img-my.csdn.net/uploads/201309/01/1378037235_7476.jpg,将这张图片下载到缓存中

private void saveResource() {
        new Thread(new Runnable() {
            @Override
            public void run() {

                try {
                    String imageUrl = "https://img-my.csdn.net/uploads/201309/01/1378037235_7476.jpg";
                    String key = hashKeyForDisk(imageUrl);
                    DiskLruCache.Editor edit = diskLruCache.edit(key);
                    if (edit != null){
                        OutputStream outputStream = edit.newOutputStream(0);
                        if (downloadUrlToStream(imageUrl,outputStream)){
                            edit.commit();
                        }else {
                            edit.abort();
                        }
                    }
                    //内存中的操作记录同步到日志文件(也就是journal文件)当中
                    diskLruCache.flush();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }
 /**
     * 下载图片到磁盘缓存
     * @param urlString
     * @param outputStream
     * @return
     */
    private boolean downloadUrlToStream(String urlString, OutputStream outputStream){

        HttpURLConnection httpURLConnection = null;
        BufferedInputStream in = null;
        BufferedOutputStream out = null;
        try {
            URL url = new URL(urlString);
            httpURLConnection = (HttpURLConnection) url.openConnection();
            in = new BufferedInputStream(httpURLConnection.getInputStream(),8*1024);
            out = new BufferedOutputStream(outputStream,8*1024);
            int b;
            while ((b = in.read())!= -1){
                out.write(b);
            }
            return true;

        } catch (IOException  e) {
            e.printStackTrace();
        }finally {
            if (httpURLConnection != null){
                httpURLConnection.disconnect();
            }

            try {
                if (out != null){
                    out.close();
                }
                if (in !=null){
                    in.close();
                }
            }catch (IOException e){

            }
        }

        return false;

    }

    public String hashKeyForDisk(String key){
        String cacheKey = null;
        try {
            MessageDigest mDigest = MessageDigest.getInstance("MD5");
            mDigest.update(key.getBytes());
            cacheKey = bytestToHextString(mDigest.digest());
        } catch (NoSuchAlgorithmException e) {
            cacheKey = String.valueOf(key.hashCode());
        }
        return cacheKey;
    }


    public String bytestToHextString(byte[] bytes){
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < bytes.length; i++) {
            String hex = Integer.toHexString(0xFF & bytes[i]);
            if (hex.length() == 1){
                sb.append("0");
            }
            sb.append(hex);
        }

        return sb.toString();
    }

调用hashKeyForDisk()方法,获取到对应的key,downloadUrlToStream()中实现下载并写入到缓存中,写入到缓存后需要调用commit()方法才能使写入生效,调用abort()方法表示放弃此次写入。

读取硬盘缓存

读取磁盘缓存DiskLruCache.get()方法

public synchronized Snapshot get(String key)

get()方法传入存入到缓存中的key

 private void getResource() {

        try {
            String imageUrl = "https://img-my.csdn.net/uploads/201309/01/1378037235_7476.jpg";
            String key = hashKeyForDisk(imageUrl);
            DiskLruCache.Snapshot snapshot = diskLruCache.get(key);
            if (snapshot != null){
                InputStream is = snapshot.getInputStream(0);
                Bitmap bitmap = BitmapFactory.decodeStream(is);
                mImage.setImageBitmap(bitmap);
            }

        } catch (IOException e) {
            e.printStackTrace();
        }

    }

移除缓存

很简单调用remove方法传入对应的key

public synchronized boolean remove(String key)

完成代码为

private void removeResource() {

        try {
            String imageUrl = "https://img-my.csdn.net/uploads/201309/01/1378037235_7476.jpg";
            String key = hashKeyForDisk(imageUrl);
            diskLruCache.remove(key);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

其它API

1.size()

返回当前缓存路径下搜友缓存数据的总字节,以byte为单位

2.flush()

将内存中的操作记录同步到日制文件journal中,这个方法非常重要,标准方法是将flush()在onPause()方法中调用

3.close()

和open()是对应的一个方法,将DiskLruCache关闭掉,关闭之后就不能调用DiskLruCache中任何操作方法,close()方法通常在onDestroy()中调用

4.delete()

删除全部的缓存数据

5.setMaxSize()

设置缓存数据的大小

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值