从零开始编写图片加载库(五)之图片缓存DiskCache
来源:互联网 发布:淘宝类目007是什么牌子 编辑:程序博客网 时间:2024/05/01 15:29
1.写在前面
在处理图片比较多的应用中,为了提高程序的响应速率,不可避免的需要硬盘缓存技术和内存缓存技术结合使用,根据图片地址去请求网络的时候,先请求内存,如果内存没有再去请求本地缓存,如果本地缓存 没有再请求网络。这是一般图片加载框架的处理思路。
2.DiskLruCache的介绍
DiskLruCache是什么?DiskLruCache是一款优秀的第三方硬盘缓存解决方案,我们熟知的网易新闻就是通过这个来缓存图片到本地。
网易新闻需要加载的图片还是挺多的,如果每次进入app都需要请求网络加载图片显然是不合适的,一方面流量的消耗还有就是性能影响,那么保存到本地是一个很好的解决方案。那么网易是怎么保存到本地的呢?
DiskLruCache的缓存目录是可以自己定义的,但是一般我们都将缓存文件保存在 /sdcard/Android/data//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); }
2.1DiskLruCache的使用
前面絮叨半天,进入正题吧,DiskLruCache的使用也是比较简单,提供了友好的访问接口。
- 打开缓存
获取DiskLruCache的方法
/** * Opens the cache in {@code directory}, creating a cache if none exists * there. * * @param directory a writable directory * @param valueCount the number of values per cache entry. Must be positive. * @param maxSize the maximum number of bytes this cache should use to store * @param maxFileCount the maximum file count this cache should store * @throws IOException if reading or writing the cache directory fails */ public static DiskLruCache open(File directory, int appVersion, int valueCount, long maxSize, int maxFileCount) throws IOException { if (maxSize <= 0) { throw new IllegalArgumentException("maxSize <= 0"); } if (maxFileCount <= 0) { throw new IllegalArgumentException("maxFileCount <= 0"); } if (valueCount <= 0) { throw new IllegalArgumentException("valueCount <= 0"); } // If a bkp file exists, use it instead. File backupFile = new File(directory, JOURNAL_FILE_BACKUP); if (backupFile.exists()) { File journalFile = new File(directory, JOURNAL_FILE); // If journal file also exists just delete backup file. if (journalFile.exists()) { backupFile.delete(); } else { renameTo(backupFile, journalFile, false); } } // Prefer to pick up where we left off. DiskLruCache cache = new DiskLruCache(directory, appVersion, valueCount, maxSize, maxFileCount); if (cache.journalFile.exists()) { try { cache.readJournal(); cache.processJournal(); cache.journalWriter = new BufferedWriter( new OutputStreamWriter(new FileOutputStream(cache.journalFile, true), Util.US_ASCII)); return cache; } catch (IOException journalIsCorrupt) { System.out .println("DiskLruCache " + directory + " is corrupt: " + journalIsCorrupt.getMessage() + ", removing"); cache.delete(); } } // Create a new empty cache. directory.mkdirs(); cache = new DiskLruCache(directory, appVersion, valueCount, maxSize, maxFileCount); cache.rebuildJournal(); return cache; }
保存文件
/** * 保存文件到硬盘 * * @param key * @param imageStream * @return * @throws IOException */public boolean save(String key, InputStream imageStream) throws IOException { DiskLruCache.Editor editor = cache.edit(key); if (editor == null) { return false; } OutputStream os = new BufferedOutputStream(editor.newOutputStream(0), DEFAULT_BUFFER_SIZE); int count; byte[] bs = new byte[DEFAULT_BUFFER_SIZE]; while ((count = imageStream.read(bs, 0, DEFAULT_BUFFER_SIZE)) != -1) { os.write(bs, 0, count); } os.flush(); editor.commit(); return true;}
获取文件
/** * 根据key去获取文件存储目录 * * @param key * @return */public File get(String key) { DiskLruCache.Snapshot snapshot = null; try { snapshot = cache.get(key); return snapshot == null ? null : snapshot.getFile(0); } catch (IOException e) { e.printStackTrace(); return null; }}
- 删除文件
/** * 根据key去删除文件 * @param key * @return */ public boolean remove(String key) { try { return cache.remove(key); } catch (IOException e) { e.printStackTrace(); return false; } }
2.2.DiskLruCache的实际应用效果
为了演示DiskLruCache的效果,建了一个项目,通过网络下载图片,将获取的文件保存到本地,通过Handler获取更新UI通知,根据下载的图片的key去本地查找图片并且显示。
package cn.sundroid.loader;import java.io.File;import java.io.IOException;import java.io.InputStream;import java.net.HttpURLConnection;import java.net.MalformedURLException;import java.net.URL;import cn.sundroid.cache.ext.LruDiskCache;import android.app.Activity;import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.os.Bundle;import android.os.Environment;import android.os.Handler;import android.util.Log;import android.widget.ImageView;public class MainActivity extends Activity { private ImageView image; private final String TAG = "ImageLoader"; private int cacheMaxSize = 10 * 1024 * 1024; //10M LruDiskCache cache; private final String IMAGE_CACHE_KEY = "image_cache_key"; private Handler handler = new Handler() { public void handleMessage(android.os.Message msg) { File file = cache.get(IMAGE_CACHE_KEY); Bitmap bitmap = BitmapFactory.decodeFile(file.getAbsolutePath()); image.setImageBitmap(bitmap); }; }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); File cacheDir = getDiskCacheDir(getApplicationContext(), "imageloader"); if (!cacheDir.exists()) { cacheDir.mkdirs(); } try { //硬盘初始化 cache = new LruDiskCache(cacheDir, cacheMaxSize, 0); } catch (IOException e1) { e1.printStackTrace(); } image = (ImageView) findViewById(R.id.image); //开启一个新线程 new Thread(new Runnable() { @Override public void run() { try { // 网络连接 HttpURLConnection connection = (HttpURLConnection) new URL( "http://img4.duitang.com/uploads/item/201111/25/20111125231822_MCxG5.thumb.600_0.jpg") .openConnection(); connection.setConnectTimeout(3 * 1000); connection.setReadTimeout(20 * 1000); // 读取文件流 InputStream is = connection.getInputStream(); Log.e(TAG, "put InputStream into memory cache"); cache.save(IMAGE_CACHE_KEY, is); // 发送一个消息给Handler用于更新消息 handler.sendEmptyMessage(0x10); } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }).start(); } //获取缓存路径 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); }}
源代码下载==》
0 0
- 从零开始编写图片加载库(五)之图片缓存DiskCache
- 从零开始编写图片加载库(四)之图片缓存MemoryCache
- 从零开始编写图片加载库(二)之AsyncTask图片下载
- 从零开始编写图片加载库(一)之Handler+Thread图片下载
- 从零开始编写图片加载库(三)之线程池图片下载
- MemoryCache和DiskCache在ListView和GridView中加载图片的总结(-)
- MemoryCache和DiskCache在ListView和GridView中加载图片的总结(二)
- 图片加载库之缓存策略和加载策略
- Android网络图片加载缓存处理库的使用---第三方库学习笔记(五)
- android从零开始(五)读取网络图片
- 加载图片(省缓存)
- Android图片加载框架之Picasso非常好的图片加载缓存库
- android 之图片异步加载,带缓存。
- 图片加载利器之Picasso(五)查漏补缺
- Android有效加载图片 之 图片缓存技术
- iOS网络编程(五) 异步加载及缓存图片-----EGO
- ListView显示图片(Volley+ImageRequest+LruCache+DiskCache)
- 图片双缓存加载
- JDK升级导致TLS证书认证失败
- 非阻塞的AlertDialog的代码实现
- Leet Code 6 ZigZag Conversion
- Redis--aof备份恢复
- POJ 1731:Orders next_permutation
- 从零开始编写图片加载库(五)之图片缓存DiskCache
- 图解测试之稳定性-如何开始稳定性测试
- C++枚举类型
- hdu 5122 简单题
- Html学习笔记5
- android笔记
- Oracle学习笔记20150908权限与角色的管理
- Android五大存储---(四大组件之一)ContentProvider(字段)
- 二叉搜索树转为双向链表(算法)