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 ...
随机推荐
- 深入理解Java虚拟机:JVM高级特性与最佳实践(第3版)请自取
最近在读,附上网盘链接 复制这段内容后打开百度网盘手机App,操作更方便哦 链接:https://pan.baidu.com/s/1U6yFeZxz9uD6sSiu-Br06g 提取码:3Wt4
- canvas的简单绘制及设置
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> </head> ...
- 趣图:我说自己菜 vs 大佬说自己菜
扩展阅读 一大波趣图:CSS的力量 趣图:嫁人就嫁程序员,大妈都懂的! 趣图:向客户介绍的产品VS实际开发的产品 如何准备校招技术面试+一只小菜鸟的面试之路 向Spring大佬低头--大量源码流出 ...
- jquery学习:
1.什么是jQuery jquery 全称 javaScript Query.是js的一个框架.本质上仍然是js. 2.jQuery的特点 支持各种主流的浏览器. 使用特别简单 拥有便捷的插件扩展机制 ...
- 刷题[WUSTCTF2020]CV Maker
解题思路 好家伙,打开一看像是cms,又看名字CV Maker.我以为直接要搜cve打了.搜了一会发现没什么啊.那先正常做把. 注册 注册成功后这里报错,猜测可能有注入点.先放在这里,继续登陆.发现是 ...
- 093 01 Android 零基础入门 02 Java面向对象 02 Java封装 01 封装的实现 03 # 088 01 Android 零基础入门 02 Java面向对象 02 Java封装 02 static关键字 03 static关键字(下)
093 01 Android 零基础入门 02 Java面向对象 02 Java封装 01 封装的实现 03 # 088 01 Android 零基础入门 02 Java面向对象 02 Java封装 ...
- Java知识系统回顾整理01基础03变量06变量的作用域
一.变量根据所处的位置对应不同的名称 变量处于不同的位置,有不同的名称 名称分别是 字段,属性 参数 局部变量 不同名称的变量,其作用域是不一样的 二.字段,属性,Field 当一个变量被声明在类下 ...
- 【题解】NOIP2018 旅行
题目戳我 \(\text{Solution:}\) 首先题目描述有一点不准确:回头是必须要走完一条路无路可走的时候才能返回. 对于树的情况:显然贪心做就完事了. 对于基环树的情况:对于一个\(n\)条 ...
- Tensorflow学习笔记No.4.1
使用CNN卷积神经网络(1) 简单介绍CNN卷积神经网络的概念和原理. 已经了解的小伙伴可以跳转到Tensorflow学习笔记No.4.2学习如和用Tensorflow实现简单的卷积神经网络. 1.C ...
- CentOS7 没有安装 ifconfig 命令
ifconfig 命令是设置或显示网络接口的程序,可以显示出我们机器的网卡信息. 除此之外, ip a 命令,也可以设置或显示网卡的信息 在 CentOS 7 下,默认 ifconfig 命令是没有安 ...