安卓笔记侠

专注安卓开发

导航

图片的三级缓存基础

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<String, Bitmap> cacheMap = new HashMap<String, Bitmap>();  
 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<Void, Void, Bitmap>() {  
 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 }

运行效果:

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

视频学习地址:http://www.gulixueyuan.com/course/112/task/1732/show

图片三级缓存进阶:https://blog.csdn.net/lovoo/article/details/51456515

posted on 2016-11-13 13:44  安卓笔记侠  阅读(974)  评论(0编辑  收藏  举报