DiskLruCache和Lrucache缓存bitmap
三级缓存,先在内存Lrucache中查找缓存,没有就去外存DiskLrucache中查找,再没有就下载,Lru不会自动删除,所以要设置最大缓存内存,后台运行Lrucache不会消失,关闭程序Disklrucache不会消失.代码有点乱,但还是可以用的
public class MainActivity extends AppCompatActivity {
private GridView gv_photo;
PhotoWall photoWall;
ImageView imageView;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView = findViewById(R.id.image);
photoWall = new PhotoWall();
}
@Override
protected void onPause() {
super.onPause();
photoWall.flushCache();
}
@Override
protected void onDestroy() {
super.onDestroy();
photoWall.cancelTask();
}
@Override
protected void onStart() {
super.onStart();
photoWall.getView();
}
public class PhotoWall {
// 声明LruCache缓存对象
private LruCache<String, Bitmap> lruCache;
// 声明DiskLruCache硬盘缓存对象
private DiskLruCache diskLruCache;
// 任务队列
private Set<LoadImageAsync> tasks;
// 声明GridView对象
private GridView gridView;
ImageView imageView;
public PhotoWall() {
this.gridView = gridView;
tasks = new HashSet<LoadImageAsync>();
/**
* 初始化内存缓存LruCache
*/
// 获取应用程序最大可占内存值
int maxMemory = (int) Runtime.getRuntime().maxMemory();
// 设置最大内存的八分之一作为缓存大小
int lruMemory = maxMemory / 8;
lruCache = new LruCache<String, Bitmap>(lruMemory) {
@Override
protected int sizeOf(String key, Bitmap bitmap) {
// 返回Bitmap对象所占大小,单位:kb
return bitmap.getByteCount();
}
};
/**
* 初始化硬盘缓存DiskLruCahce
*/
// 获取硬盘缓存路径,参数二为所在缓存路径的文件夹名称
File directory = getDiskCacheDir(getApplicationContext(), "aaa");
if (!directory.exists()) {
// 若文件夹不存在,建立文件夹
directory.mkdirs();
}
int appVersion = getAppVersion(getApplicationContext());
try {
// 参数1:缓存文件路径,参数2:系统版本号,参数3:一个缓存路径对于几个文件,参数4:缓存空间大小:字节
diskLruCache = DiskLruCache.open(directory, appVersion, 1, 1024 * 1024 * 10);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* @param context
* @param uniqueName
* @return
* 当SD卡存在或者SD卡不可被移除的时候,就调用getExternalCacheDir()方法来获取缓存路径,否则就调用getCacheDir
* ()方法来获取缓存路径。 前者获取到的就是 /sdcard/Android/data/<application
* package>/cache 这个路径 而后者获取到的是 datadata/application package>/cache
* 这个路径。
*/
public File getDiskCacheDir(Context context, String uniqueName) {
String cachePath;
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);
}
/**
* @param context
* @return 获取系统版本号
*/
public int getAppVersion(Context context) {
try {
PackageInfo info = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
return info.versionCode;
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
return 1;
}
public View getView() {
// 获取图片资源URL地址
String path ="https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=2548029202,3494755824&fm=27&gp=0.jpg";
// 获取控件实例
imageView = findViewById(R.id.image);
// 设置一个唯一标识符,避免异步加载图片时错位
// imageView.setTag(path);
// 设置默认图片
imageView.setImageResource(R.drawable.icon12);
// 根据图片URL到缓存中去找图片资源并设置
setImageFromLruCache(path, imageView);
return imageView;
}
/**
* 根据图片URL地址获取缓存中图片,若不存在去磁盘缓存中查找=》网络下载
*
* @param path
* @param imageView
*/
private void setImageFromLruCache(String path, ImageView imageView) {
Bitmap bitmap = lruCache.get(path);
if (bitmap != null) {
// 缓存存在,取出设置图片
Log.i("PhotoWallAdapter", "在内存缓存中找到");
imageView.setImageBitmap(bitmap);
} else {
// 缓存不存在,先找硬盘缓存,还不存在,就去网络下载(开启异步任务)
LoadImageAsync loadImageAsync = new LoadImageAsync();
loadImageAsync.execute(path);
// 添加任务到任务队列
tasks.add(loadImageAsync);
}
}
/**
* 取消队列中准备下载和正在下载的任务
*/
public void cancelTask() {
for (LoadImageAsync task : tasks) {
task.cancel(false);
}
}
/**
* 同步内存操作到journal文件
*/
public void flushCache() {
if (diskLruCache != null) {
try {
diskLruCache.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
class LoadImageAsync extends AsyncTask<String, Void, Bitmap> {
// 图片资源URL
String path = null;
@Override
protected Bitmap doInBackground(String... params) {
// 图片下载地址
this.path = params[0];
DiskLruCache.Snapshot snapshot = null;
OutputStream outputStream = null;
Bitmap bitmap = null;
// String pathMd5 = MD5Utils.md5(path);
String key = hashKeyForDisk(path);
// 根据图片url(md5)查找图片资源是否存在于硬盘缓存
try {
snapshot = diskLruCache.get(key);
if (snapshot == null) {
// 在磁盘缓存中没有找到图片资源
// 获取一个DiskLruCache写入对象
DiskLruCache.Editor editor = diskLruCache.edit(key);
if (editor != null) {
outputStream = editor.newOutputStream(0);
// 开启异步网络任务获取图片,并存入磁盘缓存
if (downloadUrlToStream(path, outputStream)) {
// 下载成功
Log.i("PhotoWallAdapter", "下载文件成功");
editor.commit();
} else {
editor.abort();
}
}
}
// 图片写入磁盘缓存后,再一次的查找磁盘缓存
snapshot = diskLruCache.get(key);
if (snapshot != null) {
// 若查找到,获取图片,并把图片资源写入内存缓存
bitmap = BitmapFactory.decodeStream(snapshot.getInputStream(0));
Log.i("PhotoWallAdapter", "在磁盘缓存中找到");
}
if (bitmap != null) {
// 将Bitmap对象添加到内存缓存当中
lruCache.put(path, bitmap);
}
return bitmap;
} catch (IOException e) {
e.printStackTrace();
} finally {
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
@Override
protected void onPostExecute(Bitmap bitmap) {
super.onPostExecute(bitmap);
// 根据Tag获取控件对象并设置图片
// ImageView imageView = (ImageView) gridView.findViewWithTag(path);
if (imageView != null && bitmap != null) {
// 加载图片
imageView.setImageBitmap(bitmap);
}
tasks.remove(this);
}
/**
* 根据图片URL地址下载图片,成功返回true,失败false
*
* @param urlString
* @param outputStream
* @return
*/
private boolean downloadUrlToStream(String urlString, OutputStream outputStream) {
HttpURLConnection urlConnection = null;
BufferedOutputStream out = null;
BufferedInputStream in = null;
try {
final 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;
}
}
public String hashKeyForDisk(String key) {
String cacheKey;
try {
final MessageDigest mDigest = MessageDigest.getInstance("MD5");//把uri编译为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();
}
}
}
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:id="@+id/line1"
android:orientation="vertical"
android:layout_height="match_parent"
tools:context=".MainActivity">
<ImageView
android:id="@+id/image"
android:layout_width="match_parent"
android:layout_height="200dp" />
</LinearLayout>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity"
android:hardwareAccelerated="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
DiskLruCache和Lrucache缓存bitmap的更多相关文章
- LruCache缓存bitmap(二)
Lrucache缓存程序关闭缓存自动清除,所以要在onstart方法中调用,只要不关闭程序缓存就在,除以1024是以kb为单位 public class MainActivity extends Ap ...
- LruCache缓存bitmap(一)
Lrucache是把图片缓存到内置sd卡,设置缓存容量为系统分配容量的八分之一,单位byte,超过缓存容量gc会自动回收不长使用的缓存.觉得lrucache就先map一样,放入键值对就行了,比较方便, ...
- LruCache缓存bitmap(三)
应用在网络连接上,onrestart后不会重新联网获取图片,省去了流量, public class MainActivity extends AppCompatActivity { ImageView ...
- 让App中加入LruCache缓存,轻松解决图片过多造成的OOM
上次有过电话面试中问到Android中的缓存策略,当时模糊不清的回答,现在好好理一下吧. Android中一般情况下采取的缓存策略是使用二级缓存,即内存缓存+硬盘缓存->LruCache+Dis ...
- 让App中增加LruCache缓存,轻松解决图片过多造成的OOM
上次有过电话面试中问到Android中的缓存策略,当时模糊不清的回答,如今好好理一下吧. Android中普通情况下採取的缓存策略是使用二级缓存.即内存缓存+硬盘缓存->LruCache+Dis ...
- android 缓存Bitmap - 开发文档翻译
由于本人英文能力实在有限,不足之初敬请谅解 本博客只要没有注明“转”,那么均为原创,转贴请注明本博客链接链接 Loading a single bitmap into your user interf ...
- Android源代码解析之(七)-->LruCache缓存类
转载请标明出处:一片枫叶的专栏 android开发过程中常常会用到缓存.如今主流的app中图片等资源的缓存策略通常是分两级.一个是内存级别的缓存,一个是磁盘级别的缓存. 作为android系统的维护者 ...
- LruCache缓存
LruCache通常用于实现内存缓存,采用的缓存算法是LRU(Least Recently Used)即近期最少使用算法,其核心思想是:当缓存满的时候,会优先淘汰那些近期最少使用的缓存对象. 1.Lr ...
- Android 使用 LruCache 缓存图片
在你应用程序的 UI 界面加载一张图片是一件很简单的事情,但是当你需要在界面上加载一大堆图片的时候,情况就变得复杂起来.在很多情况下,(比如使用 ListView, GridView 或者 ViewP ...
随机推荐
- hystrix文档翻译之运维
hystrix不仅用作工程可靠性还可以用来运维. 这里将会分享一个拥有100+Hystrix命令,40+线程池,每天有100亿次线程请求,2000亿次信号量请求的系统是如何使用hystrix运维的.这 ...
- JDK8在windows系统下安装
一.下载 下载地址:https://www.oracle.com/technetwork/java/javase/downloads/index.html#JDK8 目前大部分公司内部使用的还是jdk ...
- ThreadLocal源码分析与实践
ThreadLocal是什么? ThreadLocal是一个线程内部存储类,提供线程内部存储功能,在一个ThreadLocal对象中,每一个线程都存储各自独立的数据,互不干扰 示例如下: public ...
- Mac 环境下配置 MySQL 以及 Mac终端登录MySQL
1.首先mysql官网下载Mac 版 mysql直接安装 2.打开偏好设置-> MySQL -> 查看是否开启mysql服务 3.打开终端 进入mysql目录: /usr/local/my ...
- 前端性能测试工具之PageSpeed Insights
谷歌开发的一个免费的网页分析工具,在地址栏中输入被分析的网站 url 地址,点击分析 地址:https://developers.google.cn/speed/pagespeed/insights/ ...
- RabbitMQ小记(一)
1.了解消息中间件 消息中间件,Message Queue Middleware,简称MQ,又称消息对列或消息对列中间件,利用高效可靠的消息传递机制进行与平台无关的数据交流,并基于数据通信来进行分布式 ...
- Centos-操作系统相关信息-uname
uname 获取系统相关信息 相关选项 -a 显示全部信息 -m 显示系统CPU架构 x86_64 -n 显示主机名, 和 hostname 一样 -s 获取系统类型 -r 内核信息
- getchar()与putchar()
getchar() 用于读取用户从键盘输入的单个字符,它有一个整型的返回值,当发生读取错误的时候,返回整型值-1,当读取正确的时候,它会返回用户从键盘输的第一个字符的ASCII码, 当程序调用getc ...
- 06 解决Sublime Text3输入法不跟随的问题
安装原生的Sublime, 输入法是不会跟随Sublime的编译文件页面的,会失去焦点,这样写代码写文档时看起来会十分不方便,参考了一些资料,下载插件做了配置,已经在自己机器上用百度输入法测试成功,记 ...
- 简单区间dp
题目链接 对于基本区间dp,设dp[l][r]是区间l到r的最大价值. 我们可以枚举区间的长度,在枚举左端点,判断即可. 当右端点大于n,就break. dp[l][r]=max(dp[l+1][r] ...