Android图片二级缓存
想起刚開始写代码的时候,领导叫我写一个头像下载的方法,当时屁颠屁颠就写了一个图片下载的,每次都要去网络上请求,最后直接被pass掉了
当时的思路是这种
后来渐渐地就知道了有二级缓存这东西。
自己也阅读过非常多关于双缓存的文章。
APP开发到越后面。对性能的要求越高。那么双缓存的优势就逐渐体现出来了。
所谓图片双缓存。首先到执行内存中请求,再到sd卡请求,最后到网络请求,流程图例如以下
那我们从第一部開始解析
1.先看 内存缓存的代码
- public class MemoryCache implements ImageCache {
- private static final String TAG = MemoryCache.class.getSimpleName();
- private LruCache<String,Bitmap> mMemoryCache;
- public MemoryCache(){
- init();
- }
- private void init(){
- final int maxMemory = (int) (Runtime.getRuntime().maxMemory()/1024);
- final int cacheSize = maxMemory/4;
- mMemoryCache = new LruCache<String,Bitmap>(cacheSize){
- @Override
- protected int sizeOf(String key, Bitmap value) {
- return value.getRowBytes()*value.getHeight()/1024;
- }
- };
- }
- @Override
- public Bitmap get(String key) {
- Bitmap bitmap = mMemoryCache.get(key);
- if (bitmap!=null){
- Log.i(TAG,"File is exist in memory");
- }
- return mMemoryCache.get(key);
- }
- @Override
- public void put(String key, Bitmap bitmap) {
- if (get(key)==null) {
- mMemoryCache.put(key, bitmap);
- }
- }
- }
- private void init()
init()方法中对一些变量进行初始化,mMemoryCache用于在内存中缓存图片
- public Bitmap get(String key) {}
get()方法用于从内存中获得缓存
- public void put(String key, Bitmap bitmap) {}
put()方法将下载好的图片缓存到内存中,方便下次使用
2.再看sd卡缓存
- public class DiskCache implements ImageCache {
- private static final String TAG = DiskCache.class.getSimpleName();
- static String mPath ;
- public DiskCache(Context context){
- init(context);
- }
- private void init(Context context){
- // 获取图片缓存路径
- mPath = getDiskCachePath(context,"bitmap");
- File cacheDir = new File(mPath);
- if (!cacheDir.exists()) {
- cacheDir.mkdirs();
- }
- }
- @Override
- public Bitmap get(String key) {
- File file = new File(mPath+key);
- if (file.exists()){
- return BitmapFactory.decodeFile(mPath+key);
- }
- return null;
- }
- @Override
- public void put(String key, Bitmap bitmap) {
- FileOutputStream fileOutputStream = null;
- try {
- File file = new File(mPath+key);
- if (file.exists()){
- Log.i(TAG,"File is exist on disk");
- }
- fileOutputStream = new FileOutputStream(mPath+key);
- bitmap.compress(Bitmap.CompressFormat.PNG,100,fileOutputStream);
- } catch (FileNotFoundException e) {
- e.printStackTrace();
- }finally {
- CloseUtils.closeQuietly(fileOutputStream);
- }
- }
- /**
- * 依据传入的dir获得路径
- * @param context
- * @param dir
- * @return
- */
- public String getDiskCachePath(Context context, String dir) {
- String cachePath;
- if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())
- || !Environment.isExternalStorageRemovable()) {
- cachePath = context.getExternalCacheDir().getPath();
- } else {
- cachePath = context.getCacheDir().getPath();
- }
- return cachePath + File.separator + dir;
- }
- }
相同
- private void init()
init()方法中对一些变量进行初始化,mMemoryCache用于在内存中缓存图片
- public Bitmap get(String key) {}
get()方法用于从内存中获得缓存
- public void put(String key, Bitmap bitmap) {}
put()方法将下载好的图片缓存到内存中,方便下次使用
接下来我们会在一个叫DoubleCache的类中对以上两种缓存方式进行管理
- public class DoubleCache implements ImageCache {
- private static final String TAG = DoubleCache.class.getSimpleName();
- private MemoryCache mMemoryCache = null;
- private DiskCache mDiskCache = null;
- public DoubleCache(Context context){
- mMemoryCache = new MemoryCache();
- mDiskCache = new DiskCache(context);
- }
- @Override
- public Bitmap get(String url) {
- String key = url2Key(url);
- Bitmap bitmap = mMemoryCache.get(key);
- if(bitmap==null){
- bitmap = mDiskCache.get(key);
- }else {
- }
- return bitmap;
- }
- @Override
- public void put(String url, Bitmap bitmap) {
- String key = url2Key(url);
- mMemoryCache.put(key,bitmap);
- mDiskCache.put(key,bitmap);
- }
- //url转key
- private String url2Key(String url){
- String key = MD5.hashKeyForDisk(url)+".jpg";
- return key;
- }
- }
我们在获取缓存的时候先从内存中获取。当内存中击中直接返回,当内存中没有击中,则訪问sd卡。
3.看到这里,小伙伴们一定急了,这仅仅有从缓存中和sd卡中取图片,并没有从网络获取,别急。立即就来
- public class ImageLoader {
- private static final String TAG = ImageLoader.class.getSimpleName();
- private static ImageLoader sInstance;
- private DoubleCache mDoubleCache = null;
- private ExecutorService mExecutorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
- private ImageLoader(Context context) {
- mDoubleCache = new DoubleCache(context);
- }
- public static ImageLoader getInstance(Context context) {
- if (sInstance == null) {
- synchronized (ImageLoader.class) {
- sInstance = new ImageLoader(context);
- }
- }
- return sInstance;
- }
- public void displayImage(String url, ImageView imageView) {
- Bitmap bitmap = mDoubleCache.get(url);
- if (bitmap != null) {
- imageView.setImageBitmap(bitmap);
- mDoubleCache.put(url,bitmap);
- return;
- }
- submitLoadRequest(url, imageView);
- }
- private void submitLoadRequest(final String url, final ImageView imageView) {
- Log.i(TAG,"Download,url:"+url);
- imageView.setTag(url);
- mExecutorService.submit(new Runnable() {
- @Override
- public void run() {
- final Bitmap bitmap = downloadImage(url);
- if (imageView.getTag().equals(url)) {
- imageView.post(new Runnable() {
- @Override
- public void run() {
- imageView.setImageBitmap(bitmap);
- }
- });
- }
- mDoubleCache.put(url, bitmap);
- }
- });
- }
- Handler handler = new Handler(){
- @Override
- public void handleMessage(Message msg) {
- }
- };
- public Bitmap downloadImage(String url) {
- Bitmap bitmap = null;
- HttpURLConnection conn = null;
- try {
- URL url1 = new URL(url);
- conn = (HttpURLConnection) url1.openConnection();
- bitmap = BitmapFactory.decodeStream(conn.getInputStream());
- if (bitmap!=null){
- mDoubleCache.put(url,bitmap);
- }
- } catch (MalformedURLException e) {
- e.printStackTrace();
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- if (conn != null) {
- conn.disconnect();
- }
- }
- return bitmap;
- }
从
- displayImage()
方法中能够看到。假设缓存中都没有才从网络中获取
- public Bitmap downloadImage(String url) {}
下载完毕之后。把图片放到缓存中。
到这里,我们的第二张流程图就走完了。是不是非常easy。
我们在看一下是怎样使用的
- private ImageView imageView;
- private ImageView imageView2;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- imageView = (ImageView) findViewById(R.id.image);
- imageView2 = (ImageView) findViewById(R.id.image2);
- imageView.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- ImageLoader.getInstance(MainActivity.this).displayImage("http://img.my.csdn.net/uploads/201407/26/1406383299_1976.jpg", imageView);
- }
- });
- imageView2.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- ImageLoader.getInstance(MainActivity.this).displayImage("http://img.my.csdn.net/uploads/201407/26/1406383299_1976.jpg", imageView2);
- }
- });
- }
Android图片二级缓存的更多相关文章
- picasso_强大的Android图片下载缓存库
tag: android pic skill date: 2016/07/09 title: picasso-强大的Android图片下载缓存库 [本文转载自:泡在网上的日子 参考:http://bl ...
- 毕加索的艺术——Picasso,一个强大的Android图片下载缓存库,OkHttpUtils的使用,二次封装PicassoUtils实现微信精选
毕加索的艺术--Picasso,一个强大的Android图片下载缓存库,OkHttpUtils的使用,二次封装PicassoUtils实现微信精选 官网: http://square.github.i ...
- 【第五篇】Volley代码修改之图片二级缓存以及相关源码阅读(重写ImageLoader.ImageCache)
前面http://www.cnblogs.com/androidsuperman/p/8a157b18ede85caa61ca5bc04bba43d0.html 有讲到使用LRU来处理缓存的,但是只是 ...
- picasso-强大的Android图片下载缓存库
编辑推荐:稀土掘金,这是一个针对技术开发者的一个应用,你可以在掘金上获取最新最优质的技术干货,不仅仅是Android知识.前端.后端以至于产品和设计都有涉猎,想成为全栈工程师的朋友不要错过! pica ...
- Android 图片三级缓存之内存缓存(告别软引用(SoftRefrerence)和弱引用(WeakReference))
因为之前项目同事使用了图片三级缓存,今天整理项目的时候发现同事还是使用了软引用(SoftRefrerence)和弱引用(WeakReference),来管理在内存中的缓存.看到这个我就感觉不对了.脑海 ...
- Android 图片三级缓存
图片缓存的原理 实现图片缓存也不难,需要有相应的cache策略.这里采用 内存-文件-网络 三层cache机制,其中内存缓存包括强引用缓存和软引用缓存(SoftReference),其实网络不算cac ...
- android图片的缓存--节约内存提高程序效率
如今android应用占内存一个比一个大,android程序的质量亟待提高. 这里简单说说网络图片的缓存,我这边就简单的说说思路 1:网络图片,无疑须要去下载图片,我们不须要每次都去下载. 维护一张表 ...
- 如何使用picasso 对Android图片下载缓存
相比较其他,picasso的图片缓存更加简单一些,他只需要一行代码就可以表述:导入相关jar包 Picasso.with(context).load("图片路径").into(Im ...
- Android图片载入缓存框架Glide
Glide开源框架是Google推荐的图片载入和缓框架,其在Github上的开源地址是:https://github.com/bumptech/glide 当然一个Google推荐的框架肯定就是Vol ...
随机推荐
- java多线程处理导入数据拆分List集合 同步处理插入数据
原文:https://www.2cto.com/kf/201612/581174.html import org.apache.log4j.Logger; import org.apache.poi. ...
- 网页中输出漂亮格式的Php数组神器
写网页的时候经常需要在页面中打印数组,但格式特别难看,看看一个html神器吧<pre>标签,能非常标准的显示数组格式 使用的时候只需要这样打印你的数组就OK了,太好用了,神器! 只需要两句 ...
- mysql: Error Codes and Messages
Appendix B. Error Codes and MessagesTable of Contents B.1. Server Error Codes and MessagesB.2. Clien ...
- xfs mount and repair
sudo mount -t xfs /dev/sdb1 /storage xfs文件系统修复方法 2017年12月03日 10:14:19 阅读数:2749 1. 前言 首先尝试mount和umoun ...
- 三.rocketmq-console
⦁ rocketmq-console来源于https://github.com/rocketmq/rocketmq-console 1.配置IP 2.启动运行:出现此信息则表示成功 访问:in ...
- OpenWRT DNS无法解析WAN连接的内网服务器域名
系统版本OpenWrt Chaos Calmer 15.05.1,网络连接为:WAN口连接内网10.x.x.x网段,WAN口设置为静态IP.设置L2TP接口,通过L2TP访问外网.问题出现于,所有外网 ...
- SEO之巴莱多定律
SEO这个词在2007.2008年好像特别的火,尤其在2007年下半年至今,众多SEO爱好者发起了最大的一轮搜索引擎优化研究风暴,甚至最终逼迫百度等大型搜索引擎公司改变算法. SEO,确实能带来一些经 ...
- time_t和SYSTEMTIME之间的相互转换 【转】
time_t和SYSTEMTIME之间的相互转换 #include <ctime> /* **time_t转SYSTEMTIME */ SYSTEMTIME TimetToSystemTi ...
- java中Token验证
什么是Token:它是一个令牌,随机不可预测的. 为什么需要使用Token: 1,防止表单的重复提交 2:,防止跨站点的请求伪造 Token的使用流程是:首先在服务器端生成一个随机的token值并在服 ...
- 深入理解C#中的泛型(一)
为什么要有泛型? 请大家思考一个问题:由你来实现一个最简单的冒泡排序算法.假设没有使用泛型的经验.可能会毫不犹豫的写出下面代码: public class SortHelper { //參数为int数 ...