DiskLruCache 硬盘级缓存存取JSON数据

DiskLruCache 不同于LruCache,LruCache是将数据缓存到内存中去,而DiskLruCache是外部缓存,例如可以将网络下载的图片永久的缓存到手机外部存储中去,并可以将缓存数据取出来使用,DiskLruCache不是google官方所写,但是得到了官方推荐,DiskLruCache没有编写到SDK中去,如需使用可直接copy这个类到项目中去。

  1. DiskLruCache的创建
  2. DiskLruCache缓存
  3. DiskLruCache的读取
  4. DiskLruCache删除

使用前添加依赖:

implementation 'com.jakewharton:disklrucache:2.0.2'

 

缓存:

代码如下:

 /**
     * 保存要缓存的数据
     * @param path
     */
    public void saveCacheData(String path){
        try {
            String key = hashKeyForDisk(path);
            DiskLruCache.Editor editor = mDiskLruCache.edit(key);
            if (editor != null) {
                OutputStream outputStream = editor.newOutputStream(0);
                if (downloadUrlToStream(path, outputStream)) {
                    editor.commit();
                } else {
                    editor.abort();
                }
            }
            mDiskLruCache.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
/**
     * 获取保存的数据
     * @param key
     * @return
     */
    public InputStream getCacheData(String key){

        try{
            key = hashKeyForDisk(key);
            DiskLruCache.Snapshot snapshot =  mDiskLruCache.get(key);
            InputStream inputStream = snapshot.getInputStream(0);

            return inputStream;
        }catch (Exception e){

        }
        return null;
    }

 根据URL下载一个Json数据并把它写到输出流outputstream中:

 /**
     * 根据URL下载一个Json数据并把它写到输出流outputstream中
     * @param urlString
     * @param outputStream
     * @return
     */
    private boolean downloadUrlToStream(String urlString, OutputStream outputStream) {
        HttpURLConnection urlConnection = null;
        BufferedOutputStream out = null;
        BufferedInputStream in = null;
        try {
            URL url = new URL(urlString);
            urlConnection = (HttpURLConnection) url.openConnection();
            in = new BufferedInputStream(urlConnection.getInputStream(), 8 * 1024);
            out = new BufferedOutputStream(outputStream, 8 * 1024);
            int b;
            while ((b = in.read()) != -1) {
                out.write(b);
            }
            return true;
        } catch (final IOException e) {
            e.printStackTrace();
        } finally {
            if (urlConnection != null) {
                urlConnection.disconnect();
            }
            try {
                if (out != null) {
                    out.close();
                }
                if (in != null) {
                    in.close();
                }
            } catch (final IOException e) {
                e.printStackTrace();
            }
        }
        return false;
    }
  • directory表示磁盘缓存的存储路径
    缓存目录没有具体限制,可以根据需求自己的定义。一般来说,可以选择SD卡上的/sdcard/Android/data/<application package>/cache目录,这个目录是Android系统指定的应用程序缓存目录,当应用卸载时,缓存也会被系统清除;当然还可以选择sd卡上的其他目录,也可以选择data下的当前应用目录。当然,一个严禁的程序还要考虑SD卡是否存在等。
  • appVersion表示应用的版本号
    当appVersion改变时,之前的缓存都会被清除,所以如非必要,我们为其指定一个1,不再改变即可
  • valueCount表示单个节点对应的数据个数,也就是同一个key可以对应多少个缓存文件,一般来说我们都选取1.
  • maxSize缓存的总大小。

上面已经下载了数据,接着初始化DiskLruCache,并使用DiskLruCache.Editor准备缓存:

  DiskLruCache mDiskLruCache=null;

    public MyDiskLruCache(Context context) {
        try {
            File cacheDir = getDiskCacheDir(context, "MibuBean");
            if (!cacheDir.exists()){
                //创建层级文件
                cacheDir.mkdirs();
            }
            mDiskLruCache=DiskLruCache.open(cacheDir,getAppVersion(context),1,10*1024*1024);

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

 上面保存数据代码中有个hashKeyForDisk()方法,其作用是把图片URL经过MD5加密生成唯一的key值,避免了URL中可能含有非法字符问题,hashKeyForDisk()代码如下:

/**
     * 把URL经过MD5加密生成唯一的key值,
     * 避免了URL中可能含有非法字符问题
     * @param key
     * @return
     */
    public String hashKeyForDisk(String key) {
        String cacheKey;
        try {
            final MessageDigest mDigest = MessageDigest.getInstance("MD5");
            mDigest.update(key.getBytes());
            cacheKey = bytesToHexString(mDigest.digest());
        } catch (NoSuchAlgorithmException e) {
            cacheKey = String.valueOf(key.hashCode());
        }
        return cacheKey;
    }

    private String bytesToHexString(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        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();
    }

缓存数据调用:

OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder().get().url(path).build();
        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                //获取数据
                try {
                    InputStream data = myDiskLruCache.getCacheData(path);
                    String result = new String(ByteStreams.toByteArray(data));
                    initData(result);
                } catch (IOException e1) {
                    e1.printStackTrace();
                }

            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                //存入数据
                MyDiskLruCache myDiskLruCache = new MyDiskLruCache(getContext());
                myDiskLruCache.saveCacheData(path);
                String string = response.body().string();
                //Okhttp框架解析,该代码就不展示了
                initData(string);
            }
        });

运行之后:有图上内容将缓存成功

猜你喜欢

转载自blog.csdn.net/qq_41898048/article/details/82801905