700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > 安卓图片三级缓存策略与实现

安卓图片三级缓存策略与实现

时间:2021-05-23 10:14:55

相关推荐

安卓图片三级缓存策略与实现

前言:

这里说的三级缓存,分别指的是:内存缓存、文件缓存和网络这三个层面。

一般来说,我们首次加载图片,内存和文件是没有缓存的,这样我们需要从网络加载,加载完成后,我们会存到内存和文件中去;当再次加载图片的时候,我们会先查找内存有没有,如果有就直接显示内存中的图片,如果没有,我们会接着查找文件中是否有,如果文件中有,我们会显示文件中的图片,并且把它存到内存中去,这样下次我们在内存中就能找到它了。

我们之所以要做缓存,主要是为了提高效率,节省流量。但是为什么要做三级呢?为什么不只存在内存或者只存在文件中呢?这是因为内存的读取速度快,但是容易被回收,容量小,文件的读取速度次之,不过容量大,不到不得已不会被回收。

有了以上的介绍,我们已经知道了三级缓存的必要性和实施步骤,接下来,我们就要选择在每级缓存的缓存策略了。

内存缓存,最开始大家推崇的是用SoftRefrence(软引用),它只有在内存不够的情况下才会被GC回收。但是高版本的安卓系统更倾向于回收SoftRefrence,这使得SoftRefrence不那么好用了。不过,安卓在3.0之后提供了LRUCache,它采用了最近最少使用的淘汰策略。本篇文章我们的内存缓存使用的就是LruCache.

文件缓存,我们使用的是DiskLruCache点击这里下载

网络请求,这里我们使用Volley网络请求框架点击这里下载。不懂的可以看这里Android Volley入门到精通:定制自己的Request

点击这里下载本文的源代码

内存缓存LruCache

我们定义ImageCacheUtil类来进行图片的缓存,它实现了Volley的ImageLoader.ImageCache接口,改接口需要实现两个方法: 1.getBitmap : Volley请求的时候会先回调getBitmap看缓存是否有图片,没有的话才会去网络请求 2.putBitmap : Volley下载完图片的回调,实现该方法可以进行图片缓存

使用LruCache需要以下步骤 1.通过new LruCache得到LruCache的实例

// 获取应用可占内存的1/8作为缓存int maxSize = (int) (Runtime.getRuntime().maxMemory() / 8);// 实例化LruCaceh对象mLruCache = new LruCache<String, Bitmap>(maxSize) {@Overrideprotected int sizeOf(String key, Bitmap bitmap) {return bitmap.getRowBytes() * bitmap.getHeight();}};

2.在getBitmap函数中通过mLruCache.get(url)得到内存的图片,没有时返回空。 3.在putBitmap函数中通过mLruCache.put(url,bitmap)把图片存入内存。 具体用法可以看下面我贴出的代码。

文件缓存DiskLruCache

使用DiskLruCache需要以下步骤: 1.通过DiskLruCache.open(...)得到DiskLruCache的实例

//DiskLruCache实例,它的构造方法是私有的,所以我们需要通过它提供的open方法来生成。try {mDiskLruCache = DiskLruCache.open(getDiskCacheDir(MyApplication.getContext(),CACHE_FOLDER_NAME),getAppVersion(MyApplication.getContext()) , 1, DISKMAXSIZE);} catch (IOException e) {e.printStackTrace();}

2.在getBitmap函数中如果mLruCache.get(url)返回空,通过mDiskLruCache.get(key)得到DiskLruCache.Snapshot,通过BitmapFratory(snapshot.getInputStream(0))得到图片,没有时返回空

String diskKey = MD5Utils.md5(s);try {if(mDiskLruCache.get(diskKey) != null){ //文件中有//从文件中取Log.d(TAG,"从文件中取");DiskLruCache.Snapshot snapshot = mDiskLruCache.get(diskKey);Bitmap bitmap = null;if(snapshot != null){bitmap = BitmapFactory.decodeStream(snapshot.getInputStream(0));//存入内存mLruCache.put(s,bitmap);}return bitmap;}} catch (IOException e) {e.printStackTrace();}

3.在putBitmap函数中如果mDiskLruCache.get(key)==null则把图片存入文件。

//存入文件String diskKey = MD5Utils.md5(s);try {if(mDiskLruCache.get(diskKey) == null){Log.d(TAG,"存入文件");DiskLruCache.Editor editor = mDiskLruCache.edit(diskKey);if(editor != null){OutputStream outputStream = editor.newOutputStream(0);if(press(pressFormat.JPEG,100,outputStream)){mit();}else{editor.abort();}}mDiskLruCache.flush();}} catch (IOException e) {e.printStackTrace();}

下面是这个ImageCacheUtil类的全部

public class ImageCacheUtil implements ImageLoader.ImageCache {//缓存类private static LruCache<String, Bitmap> mLruCache;private static DiskLruCache mDiskLruCache;//磁盘缓存大小private static final int DISKMAXSIZE = 10 * 1024 * 1024;//路径private static String CACHE_FOLDER_NAME = "YR_ImageCache";private String TAG = ImageCacheUtil.class.getSimpleName();public ImageCacheUtil() {// 获取应用可占内存的1/8作为缓存int maxSize = (int) (Runtime.getRuntime().maxMemory() / 8);// 实例化LruCaceh对象mLruCache = new LruCache<String, Bitmap>(maxSize) {@Overrideprotected int sizeOf(String key, Bitmap bitmap) {return bitmap.getRowBytes() * bitmap.getHeight();}};//DiskLruCache实例,它的构造方法是私有的,所以我们需要通过它提供的open方法来生成。try {mDiskLruCache = DiskLruCache.open(getDiskCacheDir(MyApplication.getContext(),CACHE_FOLDER_NAME),getAppVersion(MyApplication.getContext()) , 1, DISKMAXSIZE);} catch (IOException e) {e.printStackTrace();}}/*** volley请求的时候会先回调getBitmap查看缓存中是否有图片,没有再去请求* @param s* @return*/@Overridepublic Bitmap getBitmap(String s) {if(mLruCache.get(s) != null){ //内存中有//从内存获取Log.d(TAG,"从内存获取");return mLruCache.get(s);}else {String diskKey = MD5Utils.md5(s);try {if(mDiskLruCache.get(diskKey) != null){ //文件中有//从文件中取Log.d(TAG,"从文件中取");DiskLruCache.Snapshot snapshot = mDiskLruCache.get(diskKey);Bitmap bitmap = null;if(snapshot != null){bitmap = BitmapFactory.decodeStream(snapshot.getInputStream(0));//存入内存mLruCache.put(s,bitmap);}return bitmap;}} catch (IOException e) {e.printStackTrace();}}Log.d(TAG,"从网络中取");return null;}/*** 当Volley下载完图片后会来回调putBitmap方法来将图片进行缓存* @param s* @param bitmap*/@Overridepublic void putBitmap(String s, Bitmap bitmap) {//存入内存Log.d(TAG,"存入内存");mLruCache.put(s,bitmap);//存入文件String diskKey = MD5Utils.md5(s);try {if(mDiskLruCache.get(diskKey) == null){Log.d(TAG,"存入文件");DiskLruCache.Editor editor = mDiskLruCache.edit(diskKey);if(editor != null){OutputStream outputStream = editor.newOutputStream(0);if(press(pressFormat.JPEG,100,outputStream)){mit();}else{editor.abort();}}mDiskLruCache.flush();}} catch (IOException e) {e.printStackTrace();}}//该方法会判断当前sd卡是否存在,然后选择缓存地址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();}Log.d(TAG,cachePath + File.separator + uniqueName);return new File(cachePath + File.separator + uniqueName);}//获得应用version号码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;}}

Volley下载图片

不知道Volley可以看这篇博客:Android Volley入门到精通:定制自己的Request 关于Volley进行图片下载的具体可以看这篇博客:

Android Volley入门到精通:使用Volley加载网络图片

Volley需要我们声明一个RequestQueue来维持请求队列,我们定义RequestQueueManager来进行管理。

public class RequestQueueManager {public static RequestQueue mRequestQueue = Volley.newRequestQueue(MyApplication.getContext());public static void addRequest(Request<?> request, Object object){if (object != null){request.setTag(object);}mRequestQueue.add(request);}public static void cancelAll(Object tag) {mRequestQueue.cancelAll(tag);}}

Volley给我们提供了ImageLoader类和ImageCache类用于图片下载。我们可以用ImageLoader的get(url,ImageLoader.ImageListeer,width,height)方法来下载图片 ImageLoader的使用步骤如下: 1.用new ImageLoader方法得到ImageLoader的一个实例。其中构造方法需要传入requestQueue和ImageCache(我们在介绍内存的时候的ImageCaheUtil类实现了ImageCache)

private static ImageCacheUtil mImagetCache = new ImageCacheUtil();public static ImageLoader mImageLoader = new ImageLoader(RequestQueueManager.mRequestQueue,mImagetCache);

2.用get方法进行图片下载

public static void loadImage(String url,ImageLoader.ImageListener imageListener){mImageLoader.get(url,imageListener,0,0);}public static void loadImage(String url,ImageLoader.ImageListener imageListener,int maxWidth,int maxHeight){mImageLoader.get(url,imageListener,maxWidth,maxHeight);}

3.在Activity中调用

ImageCacheManager.loadImage("/img/image/shouye/xiaoxiao/%E5%AE%A0%E7%89%A983.jpg",new ImageLoader.ImageListener() {@Overridepublic void onResponse(ImageLoader.ImageContainer imageContainer, boolean b) {progressLy.setVisibility(View.GONE);if(imageContainer.getBitmap() != null){imageView.setImageBitmap(imageContainer.getBitmap());}}@Overridepublic void onErrorResponse(VolleyError volleyError) {progressLy.setVisibility(View.GONE);}});

好了,以上就是安卓三级缓存的实现。下载源码点击这里

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。