三级缓存,先在内存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的更多相关文章

  1. LruCache缓存bitmap(二)

    Lrucache缓存程序关闭缓存自动清除,所以要在onstart方法中调用,只要不关闭程序缓存就在,除以1024是以kb为单位 public class MainActivity extends Ap ...

  2. LruCache缓存bitmap(一)

    Lrucache是把图片缓存到内置sd卡,设置缓存容量为系统分配容量的八分之一,单位byte,超过缓存容量gc会自动回收不长使用的缓存.觉得lrucache就先map一样,放入键值对就行了,比较方便, ...

  3. LruCache缓存bitmap(三)

    应用在网络连接上,onrestart后不会重新联网获取图片,省去了流量, public class MainActivity extends AppCompatActivity { ImageView ...

  4. 让App中加入LruCache缓存,轻松解决图片过多造成的OOM

    上次有过电话面试中问到Android中的缓存策略,当时模糊不清的回答,现在好好理一下吧. Android中一般情况下采取的缓存策略是使用二级缓存,即内存缓存+硬盘缓存->LruCache+Dis ...

  5. 让App中增加LruCache缓存,轻松解决图片过多造成的OOM

    上次有过电话面试中问到Android中的缓存策略,当时模糊不清的回答,如今好好理一下吧. Android中普通情况下採取的缓存策略是使用二级缓存.即内存缓存+硬盘缓存->LruCache+Dis ...

  6. android 缓存Bitmap - 开发文档翻译

    由于本人英文能力实在有限,不足之初敬请谅解 本博客只要没有注明“转”,那么均为原创,转贴请注明本博客链接链接 Loading a single bitmap into your user interf ...

  7. Android源代码解析之(七)--&gt;LruCache缓存类

    转载请标明出处:一片枫叶的专栏 android开发过程中常常会用到缓存.如今主流的app中图片等资源的缓存策略通常是分两级.一个是内存级别的缓存,一个是磁盘级别的缓存. 作为android系统的维护者 ...

  8. LruCache缓存

    LruCache通常用于实现内存缓存,采用的缓存算法是LRU(Least Recently Used)即近期最少使用算法,其核心思想是:当缓存满的时候,会优先淘汰那些近期最少使用的缓存对象. 1.Lr ...

  9. Android 使用 LruCache 缓存图片

    在你应用程序的 UI 界面加载一张图片是一件很简单的事情,但是当你需要在界面上加载一大堆图片的时候,情况就变得复杂起来.在很多情况下,(比如使用 ListView, GridView 或者 ViewP ...

随机推荐

  1. php第三天-数组的定义,数组的遍历,常规数组的操作

    0x01 数组分类 在php中有两种数组:索引数组和关联数组 索引数组的索引值是整数,以0开始.当通过位置来标识东西时用索引数组. 关联数组是以字符串作为索引值,关联数组更像操作表.索引值为列名,用于 ...

  2. Unity3d 游戏设计(一)井字棋

    3D游戏设计(一)井字棋 运行效果: 实现过程 声明变量: public Texture2D O; public Texture2D X; GUIStyle myStyle; private int ...

  3. Django-Scrapy生成后端json接口

    Django-Scrapy生成后端json接口: 网上的关于django-scrapy的介绍比较少,该博客只在本人查资料的过程中学习的,如果不对之处,希望指出改正: 以后的博客可能不会再出关于djan ...

  4. Example Code for a TMP102 I2c Thermometer————Arduino

    参考:https://playground.arduino.cc/Code/TMP102/ Example Code for a TMP102 I2c Thermometer I've fairly ...

  5. 【题解】[USACO19DEC]Milk Visits G

    题目戳我 \(\text{Solution:}\) 这题不要把思想局限到线段树上--这题大意就是求路径经过的值中\(x\)的出现性问题. 最开始的想法是值域线段树--看了题解发现直接\(vector\ ...

  6. JavaScript判断字符串中出现次数最多的字符,并统计其次数

    要求: 输出一个给定字符串``中出现次数最多的字符,并统计其次数. 实现思路: 利用charA()遍历这个字符串 把每个字符都存储给对象,如果对象没有该属性,就先幅值为1,如果存在了就+1 遍历对象, ...

  7. 版本控制系统之git

    一.简介 git是Linux内核项目发起者linus用C语言写的,主要用来做项目的版本控制追踪:git是无中心节点的分布式版本控制系统,也是目前很流行的版本控制系统:其安装简单,使用简单:相比传统的c ...

  8. 多测师讲解requests __中_高级讲师肖sir

    (1)生成报告 import unittest #导入单元测试框架 import requests #导入接口库 import time # #时间戳,导入time模块 from api.HTMLTe ...

  9. pytest文档50-命令行参数--durations统计用例运行时间

    前言 写完一个项目的自动化用例之后,发现有些用例运行较慢,影响整体的用例运行速度,于是领导说找出运行慢的那几个用例优化下. --durations 参数可以统计出每个用例运行的时间,对用例的时间做个排 ...

  10. 阅读-Calibre Library转PDF、EPUB配置

    提示:如果想恢复默认设置,点击"恢复默认值"即可 -----EPUB (MOBI同理)----- 目标:解决转换过程中图片清晰度丢失问题(分辨率太低) 右击-转换书籍-逐个转换 输 ...