现在很多App的某些功能会把图片以及内容缓存在本地,即使是没有网络的情况下也还是可以加载出之前浏览过的内容来,这些功能就是使用了DiskLruCache技术;

LruCache负责管理内存中图片的存储与释放,如果图片从内存中被移除的话,那么又需要从网络上重新加载一次图片,这显然非常耗时,所以Google又提供了一套硬盘缓存的解决方案:DiskLruCache;
DiskLruCache并没有限制数据的缓存位置,可以自由地进行设定,不过一般来说会存储在SD卡中, 当SD卡存在或者SD卡不可被移除的时候,就调用getExternalCacheDir()方法来获取缓存路径,否则就调用getCacheDir()方法来获取缓存路径。 前者获取到的就是 /sdcard/Android/data//cache 这个路径 而后者获取到的是 data/data/<application - package>/cache这个路径,接下来就用一个简单的照片墙demo来阐述DiskLruCache以及LruCache缓存技术吧;

先附上我的项目结构

DiskLruCache这个类并没有在android api中,所以需要从网上下载下来,然后加在项目中就可以了,这里我就附上链接了
https://download.csdn.net/download/qq_42889476/11485240

因为图片的话是需要机密处理的,所以我们需要一个工具类----MD5转换工具类

package com.example.disklrucache_demo;import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;public class MD5Utils {//使用MD5加密算法public static String md5(String plainText){byte[] secretBytes = null;try {secretBytes = MessageDigest.getInstance("md5").digest(plainText.getBytes());} catch (NoSuchAlgorithmException e) {throw new RuntimeException("没有md5这个算法!");}//16进制String md5Code = new BigInteger(1,secretBytes).toString(16);// 如果生成数字未满32位,需要前面补0for (int i = 0; i < 32 - md5Code.length(); i++) {md5Code = "0" + md5Code;}return md5Code;}
}

然后是数据集合

package com.example.disklrucache_demo;public class Images {public final static String[] imageThumbUrls = new String[]{"http://image.biaobaiju.com/uploads/20180211/01/1518283483-ZSaWgidtGK.jpg","http://img.51ztzj.com/upload/image/20131024/dn201310242017_670x419.jpg","http://image.biaobaiju.com/uploads/20180803/20/1533300593-nYwpoTMUEs.jpg","http://img.juimg.com/tuku/yulantu/130316/267856-1303160U31010.jpg","http://pic1.win4000.com/wallpaper/2017-10-18/59e7096016774.jpg","http://gss0.baidu.com/-Po3dSag_xI4khGko9WTAnF6hhy/zhidao/pic/item/b64543a98226cffcad22c094ba014a90f603ea88.jpg","http://img.pconline.com.cn/images/photoblog/1/0/1/5/10159318/200911/4/1257320021267_mthumb.jpg","http://img3.duitang.com/uploads/item/201605/18/20160518232450_zxyFi.thumb.700_0.jpeg","http://img.tukexw.com/img/252557a08a4ae4d1.jpg","http://img4q.duitang.com/uploads/blog/201409/18/20140918211053_zaFRk.thumb.700_0.jpeg","http://www.zhutizhijia.net/uploads/120323/24-120323155524102.jpg","http://image.biaobaiju.com/uploads/20180706/04/1530821556-qYtMwiolae.jpg","http://b-ssl.duitang.com/uploads/item/201302/17/20130217212232_xAK5C.jpeg","http://b-ssl.duitang.com/uploads/item/201201/23/20120123195204_A8CRN.thumb.700_0.jpg","http://image.yy.com/yywebalbumbs2bucket/28e43cdd19324941b73fe57c09046ddd_1487870799169.jpeg","http://img5.duitang.com/uploads/blog/201508/10/20150810145410_5xEQJ.thumb.700_0.jpeg","http://photocdn.sohu.com/20120704/Img347284777.jpg","http://img4q.duitang.com/uploads/item/201411/03/20141103115630_HMhnU.jpeg","http://img1.doubanio.com/pview/event_poster/raw/public/6eec72f07eb8c98.jpg","http://img4q.duitang.com/uploads/item/201306/23/20130623230957_fmVV4.thumb.700_0.jpeg","http://img2.ph.126.net/RJc77dzeQTv8z2CHGmzzgQ==/1828179973736115230.jpg","http://s10.sinaimg.cn/middle/950ebfd0nb5be42e39a09&690","http://g.hiphotos.baidu.com/zhidao/pic/item/ae51f3deb48f8c54fa5fd5673a292df5e1fe7fed.jpg","http://img21.mtime.cn/mg/2010/09/14/162329.60324301.jpg","http://i1.szhomeimg.com/n/2013/04/10/0410171600540.JPG","http://b-ssl.duitang.com/uploads/item/201609/18/20160918141907_WBG2A.jpeg","http://k.zol-img.com.cn/sjbbs/6319/a6318625_s.jpg","http://b-ssl.duitang.com/uploads/item/201205/16/20120516125715_AfAiz.jpeg","http://b-ssl.duitang.com/uploads/item/201206/15/20120615095518_UB3CS.jpeg","http://i1.sinaimg.cn/edu/2012/0413/U7516P42DT20120413140544.jpg","http://www.cnr.cn/newscenter/gjxw/list/201305/W020130516373227379082.jpg","http://b-ssl.duitang.com/uploads/item/201204/12/20120412130056_kKxcd.jpeg","http://img.boqiicdn.com/Data/BK/A/1301/23/img84111358931890_y.jpg","http://img3.100bt.com/upload/ttq/20130323/1364004564120.png","http://img01.tooopen.com/Downs/images/2011/7/19/sy_2011071921084512107.jpg","http://img2.shangxueba.com/img/lady_Img/20140808/17/E7EACCFD9928B5B0064022F8E0E7DB36.jpg"};
}

注:(如果程序跑起来了是默认的图片的话,建议自己去网上找一点图片的链接,然后再跑一遍就OK了)
activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context=".MainActivity"><GridViewandroid:id="@+id/grid_view"android:layout_width="match_parent"android:layout_height="match_parent"android:numColumns="3"android:verticalSpacing="10dp"android:horizontalSpacing="10dp"android:columnWidth="90dp"android:stretchMode="columnWidth"android:gravity="center"></GridView></RelativeLayout>

item_activity.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><ImageViewandroid:id="@+id/img_photo"android:layout_width="120dp"android:layout_height="120dp" /></LinearLayout>

网格布局有了,子item也有了,接下来就需要一个适配器了
流程:继承ArrayAdatper,在构造函数传入必要参数后,然后在getView方法中来设置图片源,首先先设置成一张默认的图片,然后根据图片的URL去缓存中找是否有相关联的资源,如果没找到在磁盘缓存中找,如果还是没找到再去网络上下载,然后保存在磁盘缓存里,下载资源的话是一个耗时的操作,所以开启了一个内部类Async异步类去完成,把所有的耗时操作都安排在doInBackground里执行,然后下载好了会缓存在内存和磁盘中
这个适配器的其他功能我都用代码注释好了,就不一一讲解了

package com.example.disklrucache_demo;import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Environment;
import android.util.Log;
import android.util.LruCache;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.GridView;
import android.widget.ImageView;import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashSet;
import java.util.Set;import static com.example.disklrucache_demo.MainActivity.TAG;public class ImageAdapter extends ArrayAdapter {//声明LruCache缓存对象private LruCache<String, Bitmap> lruCache;// 声明DiskLruCache硬盘缓存对象private DiskLruCache diskLruCache;//任务列表private Set<LoadImageAsync> tasks;//声明GridView对象private GridView gridView;public ImageAdapter(Context context, int textViewResourceId,String[] objects,GridView gridView) {super(context, textViewResourceId,objects);this.gridView = gridView;tasks = new HashSet<LoadImageAsync>();//初始化内存缓存LruCache,获取应用最大可占内存int MaxMemory = (int) Runtime.getRuntime().maxMemory();//设置最大内存的八分之一作为图片资源的缓存大小int LruMemory = MaxMemory / 8;lruCache = new LruCache<String, Bitmap>(LruMemory){@Overrideprotected int sizeOf(String key, Bitmap value) {//返回Bitmap对象所占大小,单位:kbreturn value.getByteCount();}};//初始化硬盘缓存DiskLruCache,获取硬盘的缓存路径,参数2为所在缓存路径的文件夹的名称File directory = getDiskCacheDir(getContext(),"bitmap");if (!directory.exists()){//若文件不存在,则创建新的文件夹directory.mkdirs();}//获取App版本号int appVersion = getAppVersion(getContext());//缓存1:缓存文件路径,参数2:系统版本号,参数3:一个缓存路径对几个文件,缓存4:缓存的空间大小try {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 这个路径 而后者获取到的是 data/data/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;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {//获取图片资源URL地址String path = (String) getItem(position);View view = null;if (convertView == null){//加载子布局view = LayoutInflater.from(getContext()).inflate(R.layout.item_activity,null);}else {view = convertView;}//获取控件实例ImageView imageView = view.findViewById(R.id.img_photo);//设置唯一一个标识符,避免异步加载时错位imageView.setTag(path);//设置默认显示图片imageView.setImageResource(R.drawable.timg);// 根据图片URL到缓存中去找图片资源并设置setImageFromLruCache(path, imageView);return view;}/*** 根据图片URL地址获取缓存中图片,若不存在去磁盘缓存中查找,磁盘中没有就进行网络下载** @param path* @param imageView*/private void setImageFromLruCache(String path,ImageView imageView){//获取图片的地址Bitmap bitmap = lruCache.get(path);if (bitmap != null){//有缓存,直接取出图片Log.d(TAG, "setImageFromLruCache: 在内存缓存中找到图片" );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>{String path = null;@Overrideprotected Bitmap doInBackground(String... strings) {//图片的下载地址this.path = strings[0];DiskLruCache.Snapshot snapshot = null;OutputStream outputStream = null;Bitmap bitmap = null;String pathMd5 = MD5Utils.md5(path);//根据图片的URL查找图片是否存在于硬盘try {snapshot = diskLruCache.get(pathMd5);if (snapshot == null){//在磁盘缓存里没有找到对应的图片资源DiskLruCache.Editor editor = diskLruCache.edit(pathMd5);if (editor != null){outputStream = editor.newOutputStream(0);// 开启异步网络任务获取图片,并存入磁盘缓存if (DownLoadToStream(path,outputStream)){//下载成功
//                        Log.d(TAG, "doInBackground: DownLoad Image Suc" );editor.commit();}}}// 图片写入磁盘缓存后,再一次的查找磁盘缓存snapshot = diskLruCache.get(pathMd5);if (snapshot != null){// 若查找到,获取图片,并把图片资源写入内存缓存bitmap = BitmapFactory.decodeStream(snapshot.getInputStream(0));Log.d(TAG, "doInBackground: 在磁盘缓存中找到");}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;}@Overrideprotected void onPostExecute(Bitmap bitmap) {super.onPostExecute(bitmap);//根据Tag获取控件对象并设置图片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 DownLoadToStream(String urlString,OutputStream outputStream){HttpURLConnection connection = null;BufferedInputStream inputStream = null;BufferedOutputStream outputStream1 = null;try {final URL url = new URL(urlString);connection = (HttpURLConnection) url.openConnection();inputStream = new BufferedInputStream(connection.getInputStream(),8*1024);outputStream = new BufferedOutputStream(outputStream,8*1024);int b;//读while ((b = inputStream.read()) != -1){//写outputStream.write(b);}return true;} catch (MalformedURLException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}finally {if (connection != null) {connection.disconnect();}try{if (outputStream != null) {outputStream.close();}if (inputStream != null) {inputStream.close();}} catch (IOException e) {e.printStackTrace();}}return false;}}
}

MainActivity类
在onPause方法里进行flush操作(更新磁盘缓存操作日志,磁盘缓存之所以能够被读取取决于日志文件

package com.example.disklrucache_demo;import androidx.appcompat.app.AppCompatActivity;import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;import com.jakewharton.disklrucache.DiskLruCache;import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;public class MainActivity extends AppCompatActivity {public static final String TAG = "MainActivity";private GridView gv_photo;private ImageAdapter adapter;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);gv_photo= findViewById(R.id.grid_view);adapter = new ImageAdapter(MainActivity.this,0,Images.imageThumbUrls,gv_photo);gv_photo.setAdapter(adapter);}@Overrideprotected void onPause() {super.onPause();adapter.flushCache();}@Overrideprotected void onDestroy() {super.onDestroy();adapter.cancelTask();}
}

附上效果图

最后的话附上一个Demo下载链接

https://download.csdn.net/download/qq_42889476/11485297

Android利用DiskLruCache和LruCache实现简单的照片墙相关推荐

  1. Android利用RecognizerIntent识别语音并简单实现打电话动作

    关于Android利用RecognizerIntent识别语音并简单实现打电话,具体看实现代码如下: package com.example.recognizerintentactivity;impo ...

  2. Android 利用viewPager FragmentPagerAdapter 做一个简单的相册视图

    说一下注意事项:你的布局需要用到viewparger 和 tabLayout 控件这两个控件要写全路径名 看图片中Tablayout的参数 设置选中 非选中 下划线颜色. 如果网络获取图片加权限 &l ...

  3. (转)[Android] 利用 ant 脚本修改项目包名

    [Android] 利用 ant 脚本修改项目包名在开发android应用项目的时候,经常会有这样的需求,一个应用项目,要求 房价上半年下行 下半年或回暖 在不同的OEM下有不同的包名,不同的资源,不 ...

  4. android 利用eclipse观察内存变化情况

    android 利用eclipse观察内存变化情况 使用方法比较简单: · 选择DDMS视图,并打开Devices视图和Heap视图 · 点击选择要监控的进程,比如:上图中我选择的是system_pr ...

  5. 【iOS-Cocos2d游戏开发之二十】精灵的基础知识点总汇(位图操作/贴图更换/重排z轴等)以及利用CCSprite与CCLayerColor制作简单遮盖层!...

    为什么80%的码农都做不了架构师?>>>     李华明Himi 原创,转载务必在明显处注明: 转载自 [黑米GameDev街区] 原文链接:  http://www.himigam ...

  6. android 新闻功能列表,Android中通过ListView的实现简单新闻列表

    Android中通过ListView的实现简单新闻列表.本文分为两个部分,第一个部分是最基础的运用ListView实现列表展示.第二个部分是运用ListView实现新闻列表的展示. 这张图片是关于控件 ...

  7. Android利用SVG实现动画效果

    系列文章目录 Android利用SVG实现动画效果 老规矩,文中/文末会放置源码 文章目录 系列文章目录 前言 一.先看看Android中一个简单的SVG图 二.pathdata中参数的定义(三角形是 ...

  8. android封装浏览器,android利用WebView实现浏览器的封装

    android提供了封装浏览器的接口,可以让开发者利用自己的view显示网页内容.今天又实现研究了一下,利用WebView显示浏览器内容,还可以利用 WebViewClient显示自己需要的内容. 效 ...

  9. 利用Kali Linux进行一些简单可操作的攻击

    利用Kali Linux进行一些简单可操作的攻击 文章目录 一.arp欺骗断网 二.内网DDOS 三.Metasploit木马远控 四.SQL注入 一.arp欺骗断网 arpspoof -i eth0 ...

最新文章

  1. git 常用命令以及其他使用笔记
  2. Easy h-index
  3. java 集合框架快速预览
  4. 我在编写《微软System Center 2012 R2私有云部署实战》中应用的一些小技巧
  5. Form Template Method(塑造模板函数)
  6. ADO.NET三个基本对象(一)
  7. 周长相等的正方形面积一定相等_三年级下册数学期末重点——面积
  8. Python matplot画散列图
  9. python bp神经网络进行预测_python实现BP神经网络回归预测模型
  10. Android学习笔记(一)——Android应用的界面编程
  11. php 保留html,PHP substr但保留HTML標簽?
  12. N54L文件服务器,N54L安装群晖需要修改的硬件设置
  13. 外国科学家有哪些黑历史? - 易智编译EaseEditing
  14. flashfxp用什么协议连接服务器,flashfxp怎么连接,flashfxp怎么连接,具体的连接方法...
  15. ubuntu 18.04下greenplum安装笔记(二)安装Greenplum的失败的尝试
  16. 小学计算机教师集体备课计实,小学科学集体备课记录(年.doc
  17. 浅谈因子分析(Factor Analysis)
  18. MS COCO数据集人体关键点评估(Keypoint Evaluation)(来自官网)
  19. 顺序表倒置java_倒置顺序表
  20. A001 - 基础 - 交换机原理简述

热门文章

  1. ubuntu 下更新命令
  2. 2,2‘-联噻吩-5,5’-二甲醛|cas32364-72-0 中间体材料
  3. axios,feach踩坑系列
  4. magic square java_LeetCode算法题-Magic Squares In Grid(Java实现)
  5. 兼容 tmux,类似 rz / sz 的 trzsz ( trz / tsz ) 发布 1.0 正式版
  6. 8月3日第壹简报,星期三,农历七月初六
  7. 计算机配置很高 但是很卡,为什么你的电脑配置很高但是玩起游戏来还是很卡?-电脑很卡怎么办...
  8. 基于ssh果蔬、水果、蔬菜销售系统
  9. qt超强绘图控件qwt - 安装及配置
  10. iOS 苹果真机鉴定