博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
图片的三级缓存基础
阅读量:6449 次
发布时间:2019-06-23

本文共 7967 字,大约阅读时间需要 26 分钟。

1.图片缓存优先级:Bitmap优于手机本地的图片文件优于服务器端的图片文件

一级缓存:内存缓存,缓存的是bitmap对象(这些对象在内存如何存储呢?一般而言有两种方式:List和Map,List根据下标来得到对象,Map根据Key得到对象,实际图片存储都是用Map)。

二级缓存:本地(SD卡)缓存,缓存的是图片文件,/storage/sdcard/Android/data/packageName/files/图片文件名(xxx.jpg)

三级缓存:远程服务器缓存,缓存的是图片文件,远程服务器上的应用中

2.如何使用三级缓存?-----如何根据图片的URL动态显示图片?

String imagePath = http://192.168.10.165:8080//L05_Web/images/f10.jpg和ImageView对象

1)。根据Url从一级缓存中取对应的bitmap对象

        如果有,显示(结束)

       如果没有,进入2

2)。从二级缓存中查找:得到文件名,并在sd卡的缓存目录下加载对应的图片得到Bitmap对象

        如果有:显示,缓存到一级缓存中(结束) 

        如果没有,进入3

3)。显示代表提示正在加载的图片,启动分线程联网请求得到Bitmap对象

        如果没有:显示提示错误的图片(结束)

        如果有:

                     显示

                     缓存到一级缓存

                     缓存到二级缓存

1 /**    2     String iamgePath = http://192.168.10.165:8080//L05_Web/images/f10.jpg和ImageView对象    3     1). 根据url从一级缓存中取对应的bitmap对象    4         如果有, 显示(结束)    5         如果没有, 进入2)    6     2). 从二级缓存中查找: 得到文件名并在sd卡的缓存目录下加载对应的图片得到Bitmap对象    7         如果有: 显示, 缓存到一级缓存中(结束)    8         如果没有, 进入3)    9     3). 显示代表提示正在加载的图片, 启动分线程联网请求得到Bitmap对象   10             如果没有: 显示提示错误的图片(结束)   11             如果有:    12                 显示   13                 缓存到一级缓存   14                 缓存到二级缓存   15  */   16 public class ImageLoader {   17        18     private Context context;   19     private int loadingImageRes;   20     private int errorImageRes;   21    22     public ImageLoader(Context context, int loadingImageRes, int errorImageRes) {   23         super();   24         this.context = context;   25         this.loadingImageRes = loadingImageRes;   26         this.errorImageRes = errorImageRes;   27     }   28    29     //用于缓存bitmap的容器对象   30     private Map
cacheMap = new HashMap
(); 31 32 /** 33 * 加载图片并显示 34 * @param imagePath 35 * @param imageView 36 */ 37 public void loadImage(String imagePath, ImageView imageView) { 38 39 //将需要显示的图片url保存到视图上 40 imageView.setTag(imagePath); 41 42 /* 43 1). 根据url从一级缓存中取对应的bitmap对象 44 如果有, 显示(结束) 45 如果没有, 进入2) 46 */ 47 Bitmap bitmap = getFromFirstCache(imagePath); 48 if(bitmap!=null) { 49 imageView.setImageBitmap(bitmap); 50 return; 51 } 52 /* 53 2). 从二级缓存中查找: 得到文件名并在sd卡的缓存目录下加载对应的图片得到Bitmap对象 54 如果有: 显示, 缓存到一级缓存中(结束) 55 如果没有, 进入3) 56 57 /storage/sdcard/Android/data/packageName/files/图片文件名(xxx.jpg) 58 */ 59 bitmap = getFromSecondCache(imagePath); 60 if(bitmap!=null) { 61 imageView.setImageBitmap(bitmap); 62 cacheMap.put(imagePath, bitmap); 63 return; 64 } 65 66 /* 67 3). 显示代表提示正在加载的图片, 启动分线程联网请求得到Bitmap对象 68 如果没有: 显示提示错误的图片(结束) 69 如果有: 70 缓存到一级缓存(分线程) 71 缓存到二级缓存(分线程) 72 显示(主线程) 73 74 */ 75 76 loadBitmapFromThirdCache(imagePath, imageView); 77 } 78 79 /** 80 * 根据图片url从三级缓存中取对应的bitmap对象并显示 81 * @param imagePath 82 * @param imageView 83 * AsyncTask 84 * loadBitmapFromThirdCache("../b.jpg", imageView) 85 * loadBitmapFromThirdCache("../f.jpg", imageView)--->imageView.setTag("../f.jpg") 86 */ 87 private void loadBitmapFromThirdCache(final String imagePath, final ImageView imageView) { 88 new AsyncTask
() { 89 protected void onPreExecute() { 90 imageView.setImageResource(loadingImageRes); 91 } 92 93 //联网请求得到bitmap对象 94 @Override 95 protected Bitmap doInBackground(Void... params) { 96 //在分线程执行, 可能需要等待一定时间才会执行 97 //在等待的过程中imageView中的tag值就有可能改变了 98 //如果改变了, 就不应该再去加载图片(此图片此时不需要显示) 99 100 Bitmap bitmap = null; 101 try { 102 103 //在准备请求服务器图片之前, 判断是否需要加载 104 String newImagePath = (String) imageView.getTag(); 105 if(newImagePath!=imagePath) {
//视图已经被复用了 106 return null; 107 } 108 109 //得到连接 110 URL url = new URL(imagePath); 111 HttpURLConnection connection = (HttpURLConnection) url.openConnection(); 112 //设置 113 connection.setConnectTimeout(5000); 114 connection.setReadTimeout(5000); 115 //连接 116 connection.connect(); 117 //发请求读取返回的数据并封装为bitmap 118 int responseCode = connection.getResponseCode(); 119 if(responseCode==200) { 120 InputStream is = connection.getInputStream();//图片文件流 121 //将is封装为bitmap 122 bitmap = BitmapFactory.decodeStream(is); 123 is.close(); 124 125 if(bitmap!=null) { 126 //缓存到一级缓存(分线程) 127 cacheMap.put(imagePath, bitmap); 128 //缓存到二级缓存(分线程) 129 // /storage/sdcard/Android/data/packageName/files/ 130 String filesPath = context.getExternalFilesDir(null).getAbsolutePath(); 131 // http://192.168.10.165:8080//L05_Web/images/f10.jpg 132 String fileName = imagePath.substring(imagePath.lastIndexOf("/")+1);// f10.jpg 133 String filePath = filesPath+"/"+fileName; 134 bitmap.compress(CompressFormat.JPEG, 100, new FileOutputStream(filePath)); 135 } 136 } 137 connection.disconnect(); 138 } catch (Exception e) { 139 e.printStackTrace(); 140 } 141 142 143 return bitmap; 144 } 145 146 protected void onPostExecute(Bitmap bitmap) {
//从联网请求图片到得到图片对象需要一定的时间, 视图可能被复用了,不需要显示 147 //在主线程准备显示图片之前, 需要判断是否需要显示 148 String newImagePath = (String) imageView.getTag(); 149 if(newImagePath!=imagePath) {
//视图已经被复用了 150 return; 151 } 152 153 //如果没有: 显示提示错误的图片(结束) 154 if(bitmap==null) { 155 imageView.setImageResource(errorImageRes); 156 } else {
//如果有, 显示 157 imageView.setImageBitmap(bitmap); 158 } 159 } 160 }.execute(); 161 } 162 163 /** 164 * 根据图片url从二级缓存中取对应的bitmap对象 165 * @param imagePath 166 * @return 167 */ 168 private Bitmap getFromSecondCache(String imagePath) { 169 170 // /storage/sdcard/Android/data/packageName/files/ 171 String filesPath = context.getExternalFilesDir(null).getAbsolutePath(); 172 // http://192.168.10.165:8080//L05_Web/images/f10.jpg 173 String fileName = imagePath.substring(imagePath.lastIndexOf("/")+1);// f10.jpg 174 String filePath = filesPath+"/"+fileName; 175 176 return BitmapFactory.decodeFile(filePath); 177 } 178 179 /** 180 * 根据图片url从一级缓存中取对应的bitmap对象 181 * @param imagePath 182 * @return 183 */ 184 private Bitmap getFromFirstCache(String imagePath) { 185 return cacheMap.get(imagePath); 186 } 187 }

运行效果:

但是,图片一直在变换,并不固定。

视频学习地址:

图片三级缓存进阶:

你可能感兴趣的文章
基于用户投票的排名算法(三):Stack Overflow
查看>>
值类型与引用类型(上)
查看>>
Activiti-Explorer 用户名与密码
查看>>
Winform 调用WCF客户端,所有服务端方法在运行的时候均找不到(编译没有问题)...
查看>>
Entity Framework 5.0系列之Code First数据库迁移
查看>>
数据库相关知识
查看>>
日志服务器设计
查看>>
Xshell生成密钥key(用于Linux 免密码登录)
查看>>
滑动到底部或顶部响应的ScrollView实现
查看>>
自己动手丰衣足食之征服jQuery插件编写
查看>>
基于业务单元的开发与部署模式
查看>>
第二代支付系统专题之报文篇(一)小额支付报文完整版(含二代新增功能业务说明)...
查看>>
非侵入式监控PHP应用性能监控分析
查看>>
LoadRunner 技巧之 脚本设计
查看>>
English Contest -- My English History
查看>>
CentOS挂载NTFS盘符问题
查看>>
Hadoop - Kylin On OLAP
查看>>
浅议javascript的内存泄露
查看>>
数据仓库专题(4)-分布式数据仓库事实表设计思考---讨论精华
查看>>
Nginx应用笔记(二)Nginx配置文件说明
查看>>