Cache【硬盘缓存工具类(包含内存缓存LruCache和磁盘缓存DiskLruCache)】
版权声明:本文为HaiyuKing原创文章,转载请注明出处!
前言
内存缓存LruCache和磁盘缓存DiskLruCache的封装类,主要用于图片缓存。
效果图
代码分析
内存缓存LruCache和磁盘缓存DiskLruCache根据实际情况进行缓存,有时候需要两者都用到,有时候只用磁盘缓存即可。
使用步骤
一、项目组织结构图
注意事项:
1、 导入类文件后需要change包名以及重新import R文件路径
2、 Values目录下的文件(strings.xml、dimens.xml、colors.xml等),如果项目中存在,则复制里面的内容,不要整个覆盖
二、导入步骤
将Cache、DiskLruCache文件复制到项目中
在AndroidManifest.xml中添加权限
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.why.project.cachedemo"> <!-- =====================Cache【硬盘缓存工具类(包含内存缓存LruCache和磁盘缓存DiskLruCache)】======================= -->
<!-- 允许程序打开网络套接字 -->
<uses-permission android:name="android.permission.INTERNET"/>
<!-- 允许程序访问有关GSM网络信息 -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!-- 允许程序访问Wi-Fi网络状态信息 -->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<!-- 在SD卡中创建与删除文件权限 -->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<!-- 允许程序读取外部存储文件 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<!-- 允许程序写入外部存储,如SD卡上写文件 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application> </manifest>
添加运行时权限的处理(本demo中采用的是修改targetSDKVersion=22)
三、使用方法
package com.why.project.cachedemo; import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView; import com.why.project.cachedemo.utils.cache.Cache; import java.net.URL; public class MainActivity extends AppCompatActivity { private Button btn_save;
private Button btn_show;
private Button btn_getsize;
private Button btn_remove; private TextView tv_size;
private ImageView img_show; private GetImgToSaveCacheTask getImgToSaveCacheTask;//获取图片并保存到缓存的异步请求类 /**内存、磁盘缓存*/
private Cache mCache;
String imgUrl = "http://img.ithome.com/newsuploadfiles/2014/12/20141223_115629_592.jpg"; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); /**必须在使用之前初始化*/
mCache = new Cache(this);
mCache.initMemoryCache();
mCache.initDiskCache(); initViews();
initEvents();
} @Override
public void onPause() {
super.onPause(); //cancel方法只是将对应的AsyncTask标记为cancel状态,并不是真正的取消线程的执行,在Java中并不能粗暴的停止线程,只能等线程执行完之后做后面的操作
if(getImgToSaveCacheTask != null && getImgToSaveCacheTask.getStatus() == AsyncTask.Status.RUNNING){
getImgToSaveCacheTask.cancel(true);
} mCache.clearCache();
System.gc();
} private void initViews() {
btn_save = (Button) findViewById(R.id.btn_save);
btn_show = (Button) findViewById(R.id.btn_show);
btn_getsize = (Button) findViewById(R.id.btn_getsize);
btn_remove = (Button) findViewById(R.id.btn_remove); tv_size = (TextView) findViewById(R.id.tv_size);
img_show = (ImageView) findViewById(R.id.img_show);
} private void initEvents() {
btn_save.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) { saveToCache(imgUrl);
}
}); btn_show.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
showImg(imgUrl);
}
}); btn_getsize.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String cacheSize = mCache.getSize();
tv_size.setText(tv_size.getText() + cacheSize);
}
}); btn_remove.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mCache.removeFromCache(mCache.hashKeyForDisk(imgUrl));
}
});
} /**显示图片*/
private void showImg(String imgUrl) {
String cacheKey = mCache.hashKeyForDisk(imgUrl);
Bitmap bitmap = mCache.getBitmapFromCache(cacheKey);//从缓存中获取图片bitmap
if(bitmap != null){
BitmapDrawable drawable = null;
Resources resources = getResources();
drawable = new BitmapDrawable(resources, bitmap);
//设置背景图片
if(Build.VERSION.SDK_INT >= 16) {
img_show.setBackground(drawable);
}else{
img_show.setBackgroundDrawable(drawable);
}
}
} /**保存图标到缓存中*/
private void saveToCache(String imgUrl){ //如果已经下载过来,那么不需要重新下载
String cacheKey = mCache.hashKeyForDisk(imgUrl);
Bitmap bitmap = mCache.getBitmapFromCache(cacheKey);//从缓存中获取图片bitmap
if(bitmap == null){
//判断是否有网络,此处注释掉
//if (HttpUtil.isNetworkAvailable(MainActivity.this)) {
//执行异步任务
GetImgToSaveCacheTask getImgTask = new GetImgToSaveCacheTask();
getImgTask.execute(imgUrl);
/*} else {
this.showShortToast(getResources().getString(R.string.httpError));
}*/
}
} /**
* 保存图标异步请求类
*/
public class GetImgToSaveCacheTask extends AsyncTask<String, Void, String> { @Override
protected void onPreExecute() {
//showProgressDialog("");//显示加载对话框
}
@Override
protected String doInBackground(String... params) {
String data = "";
if(! isCancelled()){
try {
if(params[0].equals("")){
data = "";
}else{
//下载图片并缓存
BitmapFactory.Options opts = new BitmapFactory.Options(); String cacheKey = mCache.hashKeyForDisk(params[0]);
Bitmap bitmap = null;
synchronized(mCache.mDiskCacheLock){
if(mCache.getBitmapFromCache(cacheKey) == null) {
//如果缓存中无图片,则添加到磁盘缓存和内存缓存中
bitmap = BitmapFactory.decodeStream(new URL(params[0]).openConnection().getInputStream(), null, opts);
mCache.addBitmapToMemoryCache(cacheKey, bitmap);
mCache.addBitmapToDiskCache(cacheKey, bitmap);
} else if(mCache.mMemoryCache.get(cacheKey) == null) {
//如果内存缓存中无图片,则磁盘缓存中添加到内存缓存中
bitmap = mCache.getBitmapFromDiskCache(cacheKey);
mCache.addBitmapToMemoryCache(cacheKey, bitmap);
} else if(mCache.getBitmapFromDiskCache(cacheKey) == null) {
//如果磁盘缓存中无图片,则从内存缓存中添加到磁盘缓存中
bitmap = mCache.getBitmapFromMemCache(cacheKey);
mCache.addBitmapToDiskCache(cacheKey, bitmap);
}
}
data = "success";
}
} catch (Exception e) {
e.printStackTrace();
}
}
return data;
}
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
if(isCancelled()){
return;
}
try {
if (result != null && !"".equals(result)){
//缓存成功,此处可以进行其他处理,比如显示图片
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if(! isCancelled()){
//dismissProgressDialog();//隐藏加载对话框
}
}
}
}
}
注意:
- 缓存图片建议使用异步请求,demo中使用的是AsyncTask方式;
- 异步请求缓存图片之前需要先进行网络判断,请参考HttpUtil 【判断网络连接的封装类】
缓存目录示意图:
混淆配置
无
参考资料
Android DiskLruCache完全解析,硬盘缓存的最佳方案
项目demo下载地址
https://github.com/haiyuKing/CacheDemo
Cache【硬盘缓存工具类(包含内存缓存LruCache和磁盘缓存DiskLruCache)】的更多相关文章
- 分享基于MemoryCache(内存缓存)的缓存工具类,C# B/S 、C/S项目均可以使用!
using System; using System.Collections.Generic; using System.Linq; using System.Runtime.Caching; usi ...
- Go/Python/Erlang编程语言对比分析及示例 基于RabbitMQ.Client组件实现RabbitMQ可复用的 ConnectionPool(连接池) 封装一个基于NLog+NLog.Mongo的日志记录工具类LogUtil 分享基于MemoryCache(内存缓存)的缓存工具类,C# B/S 、C/S项目均可以使用!
Go/Python/Erlang编程语言对比分析及示例 本文主要是介绍Go,从语言对比分析的角度切入.之所以选择与Python.Erlang对比,是因为做为高级语言,它们语言特性上有较大的相似性, ...
- php 缓存工具类 实现网页缓存
php 缓存工具类 实现网页缓存 php程序在抵抗大流量访问的时候动态网站往往都是难以招架,所以要引入缓存机制,一般情况下有两种类型缓存 一.文件缓存 二.数据查询结果缓存,使用内存来实现高速缓存 本 ...
- redis缓存工具类
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis ...
- redis缓存工具类,提供序列化接口
1.序列化工具类 package com.qicheshetuan.backend.util; import java.io.ByteArrayInputStream; import java.io. ...
- CookieUtils-浏览器缓存工具类
package cn.yonyong.myproject.commons.utils; import javax.servlet.http.Cookie; import javax.servlet.h ...
- 缓存工具类CacheHelper
代码: using System; using System.Collections.Generic; using System.Linq; using System.Text; using Syst ...
- 基于spring的redisTemplate的缓存工具类
pom.xml文件添加 <!-- config redis data and client jar --><dependency> <groupId>org.spr ...
- System.Web.Caching.Cache缓存帮助类
/// <summary> /// 缓存帮助类 /// </summary> public class CacheHelper { /// <summary> // ...
随机推荐
- Java 读书笔记 (二) 对象和类
Java 作为一种面向对象语言,支持以下基本概念: 多态 继承 封闭 抽象 类 对象 实例 方法 重载 对象: 是类的一个实例,有状态和行为.以人为例,黄种人.白种人.黑种人为类,每一个具体的人为类的 ...
- 高效开发 Web 单页应用解决方案
于 2017 年初,有在 Github 建立并维护一个项目:Vue Boilerplate Template,欲成就一款开箱即用 Vue + Webpack 的脚手架模版:其目标与宗旨是:根据以往经验 ...
- 第三方库API接口
第三方库API接口 InfluxDB提供了各种语言的Http API接口的封装.具体可以看这里: https://docs.influxdata.com/influxdb/v0.10/clients/ ...
- 【bzoj 3309 】 DZY Loves Math
Description 对于正整数n,定义f(n)为n所含质因子的最大幂指数.例如f(1960)=f(2^3 * 5^1 * 7^2)=3, f(10007)=1, f(1)=0.给定正整数a,b,求 ...
- BZOJ_1901_Zju2112 Dynamic Rankings_树状数组+主席树
BZOJ_1901_Zju2112 Dynamic Rankings_树状数组+主席树 题意: 给定一个含有n个数的序列a[1],a[2],a[3]……a[n],程序必须回答这样的询问:对于给定的i, ...
- MIP 脚本域名地址变更公告
尊敬的 MIP 开发者: MIP 团队为了解决 MIP-Cache 页面下 cookie 相互覆盖问题,增强站点品牌露出,在 2017 年 8 月将 MIP 的脚本域名和 MIP-Cache 页面域名 ...
- 【JVM虚拟机】(8)--深入理解Class中--方法、属性表集合
#[JVM虚拟机](8)--深入理解Class中--方法.属性表集合 之前有关class文件已经写了两篇博客: 1.[JVM虚拟机](5)---深入理解JVM-Class中常量池 2.[JVM虚拟机] ...
- 接口测试心得--签名处理(Python)
一.背景 最近负责的项目接口签名规则做了调整,第一次接触“2次认证“的方式,正好有时间,记录一下. 测试的服务A有一部分接口需要给第三方调用,这样需要对第三方有个认证,认证是由一个公共服务(API鉴权 ...
- 【原】javascript笔记之this用法
javascript中的this学习起来相对复杂,最近花了点时间研究,总结起来大概这只有5种情况,相信只要熟悉这5种用法,基本是可以解决所有的this问题,文本不介绍this设计原理,只介绍用法,阅读 ...
- 中小研发团队架构实践之生产环境诊断工具WinDbg
生产环境偶尔会出现一些异常问题,WinDbg或GDB是解决此类问题的利器.调试工具WinDbg如同医生的听诊器,是系统生病时做问题诊断的逆向分析工具,Dump文件类似于飞机的黑匣子,记录着生产环境程序 ...