【安卓笔记】硬盘缓存工具类的编写

Android DiskLruCache 源码解析 硬盘缓存的绝佳方案,零基础学习android编程 如果已经存在,那么调用。try {if (!||!||!||!||!try {break;} else {首先校验文件头,接下来调用按行读取内容。我们来看看readJournalLine中的操作。return;} else {} else {大家可以回忆下:每个记录至少有一个空格,有的包含两个空格。首先,拿到key,如果是REMOVE的记录呢,会调用; 阅读详情

DiskLruCache(https://github.com/JakeWharton/DiskLruCache)想必大家都很熟悉。不熟悉的请看这里),它是jakewharton大神写的一个开源库,提供了硬盘缓存的方案。

       但是该库的API比较简单,有时候并不能满足我们使用。比如说如果你想把缓存中的数据以Bitmap的形式返回,API并没有提供这样的方法,我们必须通过DiskLruCache#get方法返回来的Snapshot获得输入流,然后将流转化为Bitmap。另外,构建DiskLruCache时必须要传入VersionCode,CachePath等变量,而实际开发中,Versioncode通常是应用版本号,Cachepath也相对固定(要么是sd的缓存目录要么是本地的缓存目录),每次构建DiskLruCache都要写获取版本号等等重复的代码实在是太枯燥了。再比如说,写缓存时需要指定key,而这个key在项目中通常是url,而url中可能有特殊字符,这将导致写缓存失败,我们最好将url进行编码,然后使用编码后的key,而在API中并没有提供类似的方法。鉴于此,我写了一个基于DiskLruCache的工具类,进一步简化缓存操作。
    这个工具类主中的方法全部是静态的,可直接调用。它的功能有:1.构建缓存对象;2.读缓存。将缓存读为String/流/Bitmap; 3.写缓存。可以将String/File/流/Bitmap写入缓存,并支持异步写入。

   说了这么多,下面来看这个工具类是怎样写的吧。
package com.jakewharton.disklrucache;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.os.Environment;
import android.text.TextUtils;
/**
 * @author Rowandjj
 *
 *DiskLruCache的辅助工具类(DiskLruCache:http://jakewharton.github.io/DiskLruCache)
 * 提供创建/读取/写入缓存的方法,并支持异步缓存写入.
 */
public class DiskLruCacheHelper
{
	private static final long DEFAULT_MAX_SIZE = 10*1024*1024;
	
	private static ExecutorService service = null;
	/**
	 * 
	 * 创建DiskLruCache实例,默认版本号为当前应用版本号,缓存位置由getDiskCacheDir指定
	 * @param context 上下文
	 * @param cacheDirName 缓存文件夹名称
	 * @param maxSize 缓存最大值,单位是byte
	 * @return 创建成功返回DiskLruCache实例否则返回null
	 */
	public static DiskLruCache createCache(Context context,String cacheDirName,long maxSize)
	{
		DiskLruCache cache = null;
		try
		{
			 cache = DiskLruCache.open(getDiskCacheDir(cacheDirName, context), getAppVersion(context),1, maxSize);
		} catch (IOException e)
		{
			e.printStackTrace();
		}
		return cache;
	}
	/**
	 * 返回一个具有默认大小的DiskLruCache实例,默认大小为10Mb
	 * @param context
	 * @param cacheDirName
	 * @return 创建成功返回DiskLruCache实例否则返回null
	 */
	public static DiskLruCache createCache(Context context,String cacheDirName)
	{
		return createCache(context, cacheDirName, DEFAULT_MAX_SIZE);
	}
	
	/**
	 * 将图片写入缓存
	 */
	public static boolean writeBitmapToCache(DiskLruCache cache,Bitmap bitmap,String url)
	{
		return writeBitmapToCache(cache, bitmap, url, CompressFormat.JPEG,100);
	}
	
	/**
	 * 异步地将图片写入缓存。将不会不会写入结果。
	 * @param cache
	 * @param bitmap
	 * @param url
	 */
	public static void asyncWriteBitmapToCache(final DiskLruCache cache,final Bitmap bitmap,final String url)
	{
		if(service == null)
			service = Executors.newSingleThreadExecutor();
		service.execute(new Runnable()
		{
			@Override
			public void run()
			{
				writeBitmapToCache(cache, bitmap, url);
			}
		});
	}
	
	/**
	 * 将图片写入缓存
	 * @param cache 缓存对象
	 * @param bitmap 图片对象
	 * @param url 用于标识bitmap的唯一名称,通常为图片url
	 * @return true表示写入缓存成功否则为false
	 */
	public static boolean writeBitmapToCache(DiskLruCache cache,Bitmap bitmap,String url,CompressFormat format, int quality)
	{
		if(cache == null || bitmap == null || url == null || TextUtils.isEmpty(url))
			return false;
		try
		{
			DiskLruCache.Editor editor = cache.edit(generateKey(url));
			if(editor != null)
			{
				OutputStream out = editor.newOutputStream(0);
				if(bitmap.compress(format,quality, out))
				{
					editor.commit();
					return true;
				}					
				else
				{
					editor.abort();
				}
			}
		} catch (IOException e)
		{
			e.printStackTrace();
		}
		return false;
	}
	/**
	 * 异步地将图片写入缓存。将不会不会写入结果。
	 */
	public static void asyncWriteBitmapToCache(final DiskLruCache cache,final Bitmap bitmap,final String url,final CompressFormat format, final int quality)
	{
		if(service == null)
			service = Executors.newSingleThreadExecutor();
		service.execute(new Runnable()
		{
			@Override
			public void run()
			{
				writeBitmapToCache(cache, bitmap, url,format,quality);
			}
		});
	}
	
	/**
	 * 异步地将inputStram流写入缓存,将不会返回写入结果。
	 */
	public static void asyncWriteStreamToCache(final DiskLruCache cache,final InputStream in,final String url)
	{
		if(service == null)
			service = Executors.newSingleThreadExecutor();
		service.execute(new Runnable()
		{
			@Override
			public void run()
			{
				asyncWriteStreamToCache(cache, in, url);
			}
		});
	}
	
	/**
	 * 将inputStram流写入缓存
	 * @param cache
	 * @param in
	 * @param url
	 * @return
	 */
	public static boolean writeStreamToCache(DiskLruCache cache,InputStream in,String url)
	{
		if(cache == null || in == null || url == null|| TextUtils.isEmpty(url))
			return false;
		DiskLruCache.Editor editor = null;
		try
		{
			editor = cache.edit(generateKey(url));
			if(editor != null)
			{
				OutputStream out = editor.newOutputStream(0);
				BufferedInputStream bin = new BufferedInputStream(in);
				byte[] buffer = new byte[1024];
				int len = 0;
				while((len = bin.read(buffer)) != -1)
				{
					out.write(buffer, 0, len);
					out.flush();
				}
				editor.commit();
				return true;
			}
			
		} catch (IOException e)
		{
			e.printStackTrace();
		}
		return false;
	}
	/**
	 * 异步地将文件写入缓存,将不会返回写入结果。
	 */
	public static void asyncWriteFileToCache(final DiskLruCache cache,final File file,final String url)
	{
		if(service == null)
			service = Executors.newSingleThreadExecutor();
		service.execute(new Runnable()
		{
			@Override
			public void run()
			{
				writeFileToCache(cache, file, url);
			}
		});
	}
	/**
	 * 将文件写入缓存
	 * @return true表示写入成功否则写入失败
	 */
	public static boolean writeFileToCache(DiskLruCache cache,File file,String url)
	{
		if(cache == null || file == null || url == null || !file.exists() || TextUtils.isEmpty(url))
		{
			return false;
		}
		FileInputStream fin = null;
		try
		{
			fin = new FileInputStream(file);
		} catch (FileNotFoundException e)
		{
			e.printStackTrace();
		}
		return writeStreamToCache(cache, fin, url);
	}
	
	/**
	 * 异步地将字符串写入缓存,将不会返回写入结果
	 */
	public static void asyncWriteStringToCache(final DiskLruCache cache,final String str,final String url)
	{
		if(service == null)
			service = Executors.newSingleThreadExecutor();
		service.execute(new Runnable()
		{
			@Override
			public void run()
			{
				writeStringToCache(cache, str, url);
			}
		});
	}
	/**
	 * 将字符串写入缓存
	 * @param cache
	 * @param str
	 * @param url
	 * @return
	 */
	public static boolean writeStringToCache(DiskLruCache cache,String str,String url)
	{
		if(cache == null || str == null || url == null || TextUtils.isEmpty(url) || TextUtils.isEmpty(str))
		{
			return false;
		}
		DiskLruCache.Editor editor = null;
		try
		{
			editor = cache.edit(generateKey(url));
			if(editor != null)
			{
				OutputStream out = editor.newOutputStream(0);
				out.write(str.getBytes());
				out.flush();
			}
			editor.commit();
			return true;
		} catch (IOException e)
		{
			e.printStackTrace();
		}
		return false;
	}
	
	
	/**
	 * 停止内部正在写缓存的线程,
	 * 这将导致部分写缓存任务不能进行。
	 */
	public static void stop()
	{
		if(service != null)
			service.shutdownNow();
	}
	
	/**
	 * 
	 * 根据url获取缓存,并将结果以String形式返回
	 * @param cache
	 * @param url
	 * @return 成功则返回String否则返回null
	 */
	public static String readCacheToString(DiskLruCache cache,String url)
	{
		if(cache == null || url == null || TextUtils.isEmpty(url))
			return null;
		String key = generateKey(url);
		DiskLruCache.Snapshot snapshot = null;
		try
		{
			snapshot = cache.get(key);
			if(snapshot != null)
			{
				InputStream in = snapshot.getInputStream(0);
				StringBuilder builder = new StringBuilder(1024*2);
				int len = 0;
				byte[] buffer = new byte[1024];
				while((len = in.read(buffer)) != -1)
				{
					builder.append(new String(buffer,0,len));
				}
				return builder.toString();
			}
		} catch (Exception e)
		{
			e.printStackTrace();
		}
		return null;
	}
	
	/**
	 * 根据url获取缓存,并将缓存以InputStream形式返回
	 * 
	 * @param cache DiskLruCache实例
	 * @param url 缓存名
	 * @return 命中则返回InputStream流否则返回null
	 */
	public static InputStream readCacheToInputStream(DiskLruCache cache,String url)
	{
		if(cache == null || url == null || TextUtils.isEmpty(url))
			return null;
		String key = generateKey(url);
		DiskLruCache.Snapshot snapshot = null;
		try
		{
			snapshot = cache.get(key);
		} catch (IOException e)
		{
			e.printStackTrace();
		}
		if(snapshot != null)
			return snapshot.getInputStream(0);
		return null;
	}
	
	
	/**
	 * 根据url获取缓存,并将缓存以Bitmap形式返回
	 * @param cache
	 * @param url
	 * @return 成功返回bitmap,否则返回null
	 */
	public static Bitmap readCacheToBitmap(DiskLruCache cache,String url)
	{
		InputStream in = readCacheToInputStream(cache, url);
		if(in != null)
			return BitmapFactory.decodeStream(in);
		return null;
	}
	
	/**
	 * 获取缓存文件路径(优先选择sd卡)
	 * @param cacheDirName 缓存文件夹名称
	 * @param context 上下文
	 * @return
	 */
	public static File getDiskCacheDir(String cacheDirName,Context context)
	{
		String cacheDir;
		
		if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)&&!Environment.isExternalStorageRemovable())
		{
			cacheDir = getExternalCacheDir(context);
			if(cacheDir == null)//部分机型返回了null
				cacheDir = getInternalCacheDir(context);
		}else
		{
			cacheDir = getInternalCacheDir(context);
		}
		File dir =  new File(cacheDir,cacheDirName);
		if(!dir.exists())
			dir.mkdirs();
		return dir;
	}
	
	/**
	 * 获取当前app版本号
	 * @param context 上下文
	 * @return 当前app版本号
	 */
	public static int getAppVersion(Context context)
	{
		PackageManager manager = context.getPackageManager();
		int code = 1;
		try
		{
			code = manager.getPackageInfo(context.getPackageName(),0).versionCode;
		} catch (NameNotFoundException e)
		{
			e.printStackTrace();
		}
		return code;
	}
	
	
	/**
	 * 根据指定的url移除指定缓存
	 * Note:请不要是使用DiskLruCache.remove()
	 * 
	 * @param cache
	 * @param url
	 * @return
	 */
	public static boolean remove(DiskLruCache cache,String url)
	{
		if(cache == null || url == null || TextUtils.isEmpty(url))
		{
			return false;
		}
		try
		{
			return cache.remove(generateKey(url));
		} catch (IOException e)
		{
			e.printStackTrace();
		}
		return false;
	}
	
	/**
	 * 根据原始键生成新键,以保证键的名称的合法性
	 * @param key 原始键,通常是url
	 * @return
	 */
	public static String generateKey(String key)
	{
		String cacheKey;
		try
		{
			MessageDigest digest = MessageDigest.getInstance("md5");
			digest.update(key.getBytes());
			cacheKey = bytesToHexString(digest.digest());
		} catch (NoSuchAlgorithmException e)
		{
			e.printStackTrace();
			cacheKey = String.valueOf(key.hashCode());  
		}
		return cacheKey;
	}
	
	private static String bytesToHexString(byte[] bytes)
	{
		StringBuilder builder = new StringBuilder();
		for(int i = 0; i < bytes.length; i++)
		{
			String hex = Integer.toHexString(0xff&bytes[i]);
			if(hex.length() == 1)
				builder.append('0');
			builder.append(hex);
		}
		return builder.toString();
	}
	
	private static String getExternalCacheDir(Context context)
	{
		File dir = context.getExternalCacheDir();
		if(dir == null)
			return null;
		if(!dir.exists())
			dir.mkdirs();
		return dir.getPath();
	}
	
	private static String getInternalCacheDir(Context context)
	{
		File dir = context.getCacheDir();
		if(!dir.exists())
			dir.mkdirs();
		return dir.getPath();
	}
}
代码比较简单,而且都有注释,我就不过多解释了。
以后在开发中,如果需要构建DiskLruCache,调用DiskLruCacheHelper.createCache,取缓存调用 DiskLruCacheHelper. readCacheToXX,写缓存调用 DiskLruCacheHelper.writeXXtoCache,异步写调用 DiskLruCacheHelper.asyncWriteXXtoCache,移除指定缓存调用 DiskLruCacheHelper.remove。是不是很方便?

github地址: https://github.com/Rowandjj/DiskLruCacheHelper

《人工智能实战:深度学习模型改进与系统部署》,改进专栏目录和介绍 专深度学习相关项目都写在本专栏,《一次订阅解锁全部,都有源码,永久观看》,包括车牌识别、股票预测、人脸识别、风格迁移、图像修复、图像超分辨重建、图像分割等任务,Web/PyQt系统实现。引入Transformer、Swin Transformer、DenseNet、ViT、ConvNeXt等算法实战,提供卷积改进,魔改对比实验,模型剪枝,模型蒸馏,模型量化,全网独家整合改进专栏,为不同领域的同学发表论文提供了大力支持。 阅读详情

相关推荐

麒麟操作系统安装教程(保姆级)

本文介绍了如何在VM中安装麒麟操作系统,文章详细的介绍了麒麟操作系统按钻过步骤。

啊渊的专栏 1万+

一行代码搞定三级缓存

Android的三级缓存,其中主要的就是内存缓存硬盘缓存,用到分别是LruCache和DisLruCache。 LruCache是Android 3.1所提供的一个缓存类,所以在Android中可以直接使用LruCache实现内存缓存。而DisLruCache目前在Android 还不是Android SDK的一部分,但Android官方文档推荐使用该算法来实现硬盘缓存。 简单使用 Cache...

白云天的博客 1312

Android 数据缓存工具类

Android 数据缓存工具类,实现json数据缓存,字符串缓存等,带过期时间

Android缓存框架 DiskLruCache

笑谈风云,一语定乾坤。大家好,我是皖江。今天,我继续和大家分享我的Android框架学习经验之路。上次我熟悉了Android自带的二级内存缓存机制LruCache的使用,这次来学习由第三方JakeWharton的git开源项目DiskLruCache.

皖江的博客 857

DiskLruCache 的使用及源码解析

DiskLruCache 用于实现存储设备缓存,即磁盘缓存,它通过将缓存对象写入文件系统从而实现缓存的效果。DiskLruCache 得到了 Android 官方文档的推荐,但它不属于 Android SDK 的一部分,它的源码及网址文末会贴出来。下面分别从 DiskLruCache 的创建、缓存查找和缓存添加这三个方面来介绍 DiskLruCache 的使用方式。

Chittyo 2980

android 缓存工具类,android 缓存工具类 SharePreferenceUtil

各种数据类型的put和get都已经实现,且实现了缓存的clear和remove方法。直接上码:public class SharePreferenceUtil {private static final String TAG = SharePreferenceUtil.class.getSimpleName();private static final String DEFAULT_SHARE_N...

weixin_29738537的博客 455

Kotlin进阶-4-Bitmap压缩与缓存

* 1.质量压缩 像素点 AB CD 压缩后 AA AA * 原理:通过算法抠掉(同化)了图片中的一些某个些点附近相近的像素,达到降低质量介绍文件大小的目的。 * 减小了图片质量 * 注意:它其实只能实现对file的影响,对加载这个图片出来的bitmap内存是无法节省的,还是那么大。 * 因为bitm...

Yo.o 2729

Android缓存机制详解之硬盘缓存DiskLruCache

android 大图片OOM处理,DiskLruCache高效加载图片最佳方案

wuchuang 1273

android DiskCacheDir 硬盘缓存

介绍 ​ DiskLruCache硬盘缓存,他并没有显示 数据的缓存位置,可以自由的设置,但是通常情况下 程序员都会将缓存的位置选为 /sdcard/Android/data//cache 这个路径。在这个路径有两个好处,第一:这是存储在 SD 卡上的,因此不会对内存有什么影响,第二:这个路径被Android 认定为 应用程序的缓存路径,当程序卸载时,这里的我数据也会被 清除掉,这样就不...

345丶 1264

Android DiskLruCache完全解析,硬盘缓存的最佳方案

记得在很早之前,我有写过一篇文章Android高效加载大图、多图解决方案,有效避免程序OOM,这篇文章是翻译自Android Doc的,其中防止多图OOM的核心解决思路就是使用LruCache技术。但LruCache只是管理了内存中图片的存储与释放,如果图片从内存中被移除的话,那么又需要从网络上重新加载一次图片,这显然非常耗时。对此,Google又提供了一套硬盘缓存的解决方案,DiskLruCache(非Google官方编写,但获得官方认证)。只可惜,Android Doc中并没有对DiskLruCache

郭霖的专栏 15万+

Android缓存机制——DiskLruCache硬盘缓存

一、Android中的缓存策略 一般来说,缓存策略主要包含缓存的添加、获取和删除这三类操作。如何添加和获取缓存这个比较好理解,那么为什么还要删除缓存呢?这是因为不管是内存缓存还是硬盘缓存,它们的缓存大小都是有限的。当缓存满了之后,再想其添加缓存,这个时候就需要删除一些旧的缓存并添加新的缓存。 因此LRU(Least Recently Used)缓存算法便应运而生,LRU是近期最少使用的算法,它的核...

翟浩浩Android专栏 396

Android Glide数据更新及内存缓存硬盘缓存清理

Android的Glide在加载图片时候内部默认使用了缓存机制,Glide的缓存机制分为两级,第一级是内存缓存,然后第二级是硬盘缓存缓存的过程首先是在内存中缓存,然后将加载的图片资源缓存硬盘,这样就可以在随后的再次加载中使用缓存了, Glide使用缓存时候首先要检查内存这一层级是否缓存了相应的缓存,如果有,则直接使用,如果没有,则深入到硬盘缓存中检查是否有,如果有,则加载之,如果到这一步骤还

Chengda1995的博客 814

Android DiskLruCache 硬盘缓存案例

文章来源:http://blog.csdn.net/guolin_blog/article/details/28863651 DisKLruCache是Google提供的一套硬盘缓存的解决方案(非Google官方编写,但是已获得官方认证) 存储地址 外部存储:/sdcard/Android/data/.../cache 手机存储:Android/data/.../cache 下载Di...

u014736670的专栏 504

Android 缓存Bitmaps

注意:在这个例子中,1/8的应用内存被分配给缓存。在一个普通的/hdpi设备上最低也在4M左右(32/8)。一个分辨率为800*480的设备上,全屏的填满图片的GridView占用的内存约1.5M(800*480*4字节),因此这个大小的内存可以缓存2.5页左右的图片。当加载一个Bitmap到ImageView中,先要检查LruCache。如果有相应的数据,则立即用来更新ImageView,否则将启动后台线程来处理这个图片。if (bitmap!

bfhye16552的博客 887

android加载多图 LruCache与硬盘缓存融为一体

这两天工作之余,刷了一些博客,了解了android利用缓存的一些东西,想必大家也都有一些相关的经验,新手不了解也没有关系,本博文就给大家介绍一下缓存的使用。 ——————————————————-我是分割线———————————————— 首先简单介绍一下内缓存,图片加载使用内缓存最多的应该是LruCache,我们可以对这个类设置泛型LruCachemInnerCache = new Lr

301

Android实现硬盘缓存

Android实现硬盘缓存的步骤: 开辟一块空间,也就是目录 为缓存的图片生成一个唯一的名字,设置图片的后缀名 缓存图片到目录中 清空缓存图片 下面按照以上步骤用代码实现。 1.开辟一块空间2.为缓存的图片生成一个唯一的名字,设置图片的后缀名,这个有多种方法,这里介绍两种,根据网络图片的路径生成HashCodeString.valueOf(imageUrl.hashCode());使用Md5算法对

su_buju的博客 780

Android 的二级缓存如斯简单

*要想成为高级安卓工程师,必须掌握许多基础的知识。**在工作中,这些原理可以极大的帮助我们理解技术,在面试中,更是可以帮助我们应对大厂面试官的刁难。参考docs.qq.com/doc/DSkNLaERkbnFoS0ZF参考docs.qq.com/doc/DSkNLaERkbnFoS0ZF。

2401_85955108的博客 1064

基于C++和Pure-pursuit算法实现的路径跟踪和给予LQR的轨迹跟踪+源代码+文档说明+脚本(高分项目)

<项目介绍>项目博客地址https://blog.csdn.net/2301_78627004/article/details/13958521 目录概述routing_planning/Astart改进针对A*算法做出优化:加入靠近路沿的启发函数,并对生成的轨迹点做了均值滤波处理,使轨迹更加平滑。routing_planning/ros/src-不懂运行,下载完可以私聊问,可远程教学该资源内项目源码是个人的毕设,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用!1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。--------

上一篇: 【安卓笔记】Volley全方位解析,带你从源码的角度彻底理解
下一篇: 【安卓笔记】CardView+RecyclerView使用示例
rowandjj
博客等级 码龄14年 740粉丝 247原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值