android-jamendo源码学习之ImageView扩展类——RemoteImageView

精彩继续~~在 android-jamendo源码学习(二)——HomeActivity中我们遇到了RemoteImageView,一个自定义的可以从服务器下载图片的控件。后面肯定还会用到,所以拿出来在这里分析下这个控件。

首先给出源代码:

RemoteImageView
  1 /**
  2  * ImageView extended class allowing easy downloading
  3  * of remote images
  4  * 
  5  * @author Lukasz Wisniewski
  6  */
  7 public class RemoteImageView extends ImageView{
  8     
  9     /**
 10      * Maximum number of unsuccesful tries of downloading an image
 11      */
 12     private static int MAX_FAILURES = 3;
 13 
 14     public RemoteImageView(Context context, AttributeSet attrs, int defStyle) {
 15         super(context, attrs, defStyle);
 16         mContext = context;
 17         init();
 18     }
 19 
 20     public RemoteImageView(Context context, AttributeSet attrs) {
 21         super(context, attrs);
 22         mContext = context;
 23         init();
 24     }
 25 
 26     public RemoteImageView(Context context) {
 27         super(context);
 28         mContext = context;
 29         init();
 30     }
 31 
 32     /**
 33      * Sharable code between constructors
 34      */
 35     private void init(){
 36         mTimeDiff = DAYS_OF_CACHE*24*60*60*1000L;    
 37     }
 38     
 39     /**
 40      * Remote image location
 41      */
 42     private String mUrl;
 43     
 44     /**
 45      * Currently successfully grabbed url
 46      */
 47     private String mCurrentlyGrabbedUrl;
 48     
 49     /**
 50      * Remote image download failure counter
 51      */
 52     private int mFailure;
 53 
 54     /**
 55      * Position of the image in the mListView
 56      */
 57     private int mPosition;
 58 
 59     /**
 60      * ListView containg this image
 61      */
 62     private ListView mListView;
 63     
 64     /**
 65      * Default image shown while loading or on url not found
 66      */
 67     private Integer mDefaultImage;
 68 
 69     private long mTimeDiff;
 70     
 71     //init value diffrent that possible values of mCacheSize
 72     private static int mPrevCacheSize= 1;
 73     private static int mCacheSize= 150;
 74     
 75     private Context mContext;
 76     
 77     private final static String ALBUMS= "albums";
 78     private final static String ALBUMS_CONV= "bgc";
 79     private final static String RADIOS= "radios";
 80     private final static String RADIOS_CONV= "sbf";
 81     private final static String COVERS= "covers";
 82     private final static String COVERS_CONV= "dpw";
 83     private final static String ALBUM_COVER_MARKER= "1.500";
 84     private final static String JAMENDO_DIR= "Android/data/com.teleca.jamendo";
 85     private final static int MB = 1048576;    
 86     //every DAYS_OF_CACHE the radio and album thumbnails jpegs are deleted
 87     private final static int DAYS_OF_CACHE= 45;
 88     //minimum free space on sd card to enable cache
 89     private final static int FREE_SD_SPACE_NEEDED_TO_CACHE= 10;
 90     
 91     
 92 
 93     /**
 94      * Loads image from remote location
 95      * 
 96      * @param url eg. http://random.com/abz.jpg
 97      */
 98     public void setImageUrl(String url){
 99         
100         
101         if (mUrl != null && mUrl.equals(url) && (mCurrentlyGrabbedUrl == null ||
102                 (mCurrentlyGrabbedUrl != null && !mCurrentlyGrabbedUrl.equals(url)))) {
103             mFailure++;            
104             if(mFailure > MAX_FAILURES){
105                 Log.e(JamendoApplication.TAG, "Failed to download "+url+", falling back to default image");
106                 loadDefaultImage();
107                 return;
108             }
109         } else {
110             mUrl = url;
111             mFailure = 0;
112         }
113 
114         updateCacheSize();
115         
116         if (mCacheSize>0 && (url.contains(ALBUMS) || url.contains(RADIOS))) {            
117             String fileName = convertUrlToFileName(url);
118             String dir = getDirectory(fileName);
119             String pathFileName = dir + "/" + fileName;                        
120             Bitmap tbmp = BitmapFactory.decodeFile(pathFileName);
121             if (tbmp == null) {
122                 Log.d(JamendoApplication.TAG, "Image is not present, try to download");
123                 try{
124                     new DownloadTask().execute(url);
125                 } catch (RejectedExecutionException e) {
126                     // do nothing, just don't crash
127                 }
128             } else {
129                 Log.i(JamendoApplication.TAG, "Loading album cover from file");
130                 this.setImageBitmap(tbmp);
131                 updateFileTime(dir,fileName );                
132             }
133             removeAlbumCoversCache(dir, fileName);
134             removeRadioCoversCache(dir, fileName);
135             
136         }
137         else {
138             Log.i(JamendoApplication.TAG, "File not cached supported" + url);
139             ImageCache imageCache = JamendoApplication.getInstance()
140                     .getImageCache();
141             if (imageCache.isCached(url)) {                
142                 this.setImageBitmap(imageCache.get(url));
143             } else {
144                 try {
145                     Log.i(JamendoApplication.TAG, "Image is not present, try to download");
146                     new DownloadTask().execute(url);
147                 } catch (RejectedExecutionException e) {
148                     // do nothing, just don't crash
149                 }
150             }
151         }
152     }
153     
154     /**
155      * Sets default local image shown when remote one is unavailable
156      * 
157      * @param resid
158      */
159     public void setDefaultImage(Integer resid){
160         mDefaultImage = resid;
161     }
162     
163     /**
164      * Loads default image
165      */
166     private void loadDefaultImage(){
167         if(mDefaultImage != null)
168             setImageResource(mDefaultImage);
169     }
170     
171     /**
172      * Loads image from remote location in the ListView
173      * 
174      * @param url eg. http://random.com/abz.jpg
175      * @param position ListView position where the image is nested
176      * @param listView ListView to which this image belongs
177      */
178     public void setImageUrl(String url, int position, ListView listView){
179         mPosition = position;
180         mListView = listView;
181         setImageUrl(url);
182     }
183 
184     /**
185      * Asynchronous image download task
186      * 
187      * @author Lukasz Wisniewski
188      */
189     class DownloadTask extends AsyncTask<String, Void, String>{
190         
191         private String mTaskUrl;
192         private Bitmap mBmp = null;
193 
194         @Override
195         public void onPreExecute() {
196             loadDefaultImage();
197             super.onPreExecute();
198         }
199 
200         @Override
201         public String doInBackground(String... params) {
202 
203             mTaskUrl = params[0];
204             InputStream stream = null;
205             URL imageUrl;
206             Bitmap bmp = null;
207 
208             try {
209                 imageUrl = new URL(mTaskUrl);
210                 try {
211                     stream = imageUrl.openStream();
212                     bmp = BitmapFactory.decodeStream(stream);
213                     try {
214                         if(bmp != null){
215                                 mBmp = bmp;
216                                 JamendoApplication.getInstance().getImageCache().put(mTaskUrl, bmp);
217                                 Log.d(JamendoApplication.TAG, "Image cached "+mTaskUrl);
218                             
219                         } else {
220                             Log.w(JamendoApplication.TAG, "Failed to cache "+mTaskUrl);
221                         }
222                     } catch (NullPointerException e) {
223                         Log.w(JamendoApplication.TAG, "Failed to cache "+mTaskUrl);
224                     }
225                 } catch (IOException e) {
226                     Log.w(JamendoApplication.TAG, "Couldn't load bitmap from url: " + mTaskUrl);
227                 } finally {
228                     try {
229                         if(stream != null){
230                             stream.close();
231                         }
232                     } catch (IOException e) {}
233                 }
234 
235             } catch (MalformedURLException e) {
236                 e.printStackTrace();
237             }
238             return mTaskUrl;
239         }
240 
241         @Override
242         public void onPostExecute(String url) {
243             super.onPostExecute(url);
244             
245             // target url may change while loading
246             if(!mTaskUrl.equals(mUrl))            {
247                 
248                 if(url.contains(ALBUMS) || url.contains(RADIOS) ){
249                     saveBmpToSd(mBmp, url);                    
250                 }
251                 return;
252             }
253             
254             
255             Bitmap bmp = JamendoApplication.getInstance().getImageCache().get(url);
256             if(bmp == null){
257                 Log.w(JamendoApplication.TAG, "Trying again to download " + url);
258                 RemoteImageView.this.setImageUrl(url);
259             } else {
260                 
261                 // if image belongs to a list update it only if it's visible
262                 if(mListView != null)
263                     if(mPosition < mListView.getFirstVisiblePosition() || mPosition > mListView.getLastVisiblePosition())
264                         return;
265                 
266                         
267                 RemoteImageView.this.setImageBitmap(bmp);                
268                 mCurrentlyGrabbedUrl = url;                
269                 if(url.contains(ALBUMS) || url.contains(RADIOS) ){                
270                     saveBmpToSd(mBmp, url);
271                 }                
272             }
273         }
274 
275     };
276     
277     private void saveBmpToSd(Bitmap bm, String url) {
278         
279         if (bm == null) {            
280             return;
281         }
282         
283         if (mCacheSize == 0){            
284             return;
285         }
286 
287         if (FREE_SD_SPACE_NEEDED_TO_CACHE > freeSpaceOnSd()) {
288             Log.w(JamendoApplication.TAG, "Low free space on sd, do not cache");
289             return;
290         }
291         String filename = convertUrlToFileName(url);
292         String dir = getDirectory(filename);
293 
294         File file = new File(dir + "/" + filename);
295 
296         try {
297             file.createNewFile();
298             OutputStream outStream = new FileOutputStream(file);
299             bm.compress(Bitmap.CompressFormat.JPEG, 100, outStream);
300             outStream.flush();
301             outStream.close();
302 
303             Log.i(JamendoApplication.TAG, "Image saved to sd");
304 
305         } catch (FileNotFoundException e) {
306             Log.w(JamendoApplication.TAG, "FileNotFoundException");
307 
308         } catch (IOException e) {
309             Log.w(JamendoApplication.TAG, "IOException");
310         }
311 
312     }
313 
314     private String convertUrlToFileName(String url) {
315         String filename = url;
316         filename = filename.replace("http://imgjam.com/", "");
317         filename = filename.replace("/", ".");
318         filename = filename.replace("jpg", "dat");
319 
320         // do filename complicated, hard to read by user while using sd
321         if (filename.contains(ALBUMS)) {
322             filename = filename.replace(ALBUMS, ALBUMS_CONV);
323         }
324         if (filename.contains(COVERS)) {
325             filename = filename.replace(COVERS, COVERS_CONV);
326         }
327         if (filename.contains(RADIOS)) {
328             filename = filename.replace(RADIOS, RADIOS_CONV);
329         }
330         
331         return filename;
332     }
333 
334     private String getDirectory(String filename) {
335 
336         String extStorageDirectory = Environment.getExternalStorageDirectory()
337                 .toString();
338 
339         String dirPath = extStorageDirectory + "/" + JAMENDO_DIR;
340         File dirFile = new File(dirPath);
341         dirFile.mkdirs();
342 
343         dirPath = dirPath + "/dat0";
344         dirFile = new File(dirPath);
345         dirFile.mkdir();
346 
347         return dirPath;
348     }
349 
350     private void updateFileTime(String dir, String fileName) {
351         // update time of album large covers        
352         if (!fileName.contains(ALBUM_COVER_MARKER)) {
353             return;
354         }
355         File file = new File(dir, fileName);        
356         long newModifiedTime = System.currentTimeMillis();
357         file.setLastModified(newModifiedTime);
358         
359     }
360 
361     private void removeAlbumCoversCache(String dirPath, String filename) {
362 
363         if (!filename.contains(ALBUM_COVER_MARKER)) {
364             return;
365 
366         }
367 
368         File dir = new File(dirPath);
369         File[] files = dir.listFiles();
370 
371         if (files == null) {
372             // possible sd card is not present/cant write
373             return;
374         }
375 
376         int dirSize = 0;
377 
378         for (int i = 0; i < files.length; i++) {
379             if (files[i].getName().contains(ALBUM_COVER_MARKER)) {
380                 dirSize += files[i].length();
381             }
382         }
383 
384         
385         
386         if (dirSize > mCacheSize * MB || FREE_SD_SPACE_NEEDED_TO_CACHE > freeSpaceOnSd()) {
387             int removeFactor = (int) ((0.4 * files.length) + 1);
388             Arrays.sort(files, new FileLastModifSort());
389             Log.i(JamendoApplication.TAG, "Clear some album covers cache files ");
390             for (int i = 0; i < removeFactor; i++) {
391                 if (files[i].getName().contains(ALBUM_COVER_MARKER)) {
392                     files[i].delete();                
393                 }
394             }
395         }
396 
397     }
398 
399     private void removeRadioCoversCache(String dirPath, String filename) {
400 
401         if (filename.contains(ALBUM_COVER_MARKER)) {
402             return;
403         }
404 
405         File file = new File(dirPath, filename);
406         if (file.lastModified() != 0
407                 && System.currentTimeMillis() - file.lastModified() > mTimeDiff) {
408             
409                         
410             Log.i(JamendoApplication.TAG, "Clear some album or radio thumbnail cache files ");
411             file.delete();
412         }
413 
414     }
415 
416     private void clearCache() {
417         
418         String extStorageDirectory = Environment.getExternalStorageDirectory()
419                 .toString();
420 
421         String dirPath = extStorageDirectory + "/" + JAMENDO_DIR + "/dat0";
422         File dir = new File(dirPath);
423         File[] files = dir.listFiles();
424 
425         if (files == null) {
426             // possible that sd card is not present/can't write
427             return;
428         }
429 
430         for (int i = 0; i < files.length; i++) {
431             files[i].delete();
432         }
433         
434     }
435 
436     private int freeSpaceOnSd() {
437         StatFs stat = new StatFs(Environment.getExternalStorageDirectory()
438                 .getPath());
439         double sdFreeMB = ((double) stat.getAvailableBlocks() * (double) stat
440                 .getBlockSize()) / MB;
441 
442         return (int) sdFreeMB;
443     }
444     
445     public void updateCacheSize() {
446         
447         mPrevCacheSize = mCacheSize;        
448         mCacheSize = Integer.parseInt(PreferenceManager
449                 .getDefaultSharedPreferences(mContext).getString(
450                         "cache_option", "100"));
451         
452         if(mPrevCacheSize!= 0 && mCacheSize == 0 ){
453         //do it only once after changing mCacheSize value to 0
454             clearCache();
455         }
456 
457     }
458 
459 }
460 
461 
462 class FileLastModifSort implements Comparator<File>{
463 
464     public int compare(File arg0, File arg1) {
465         if (arg0.lastModified() > arg1.lastModified()) {
466             return 1;
467         } else if (arg0.lastModified() == arg1.lastModified()) {
468             return 0;
469         } else {
470             return -1;
471         }
472 
473     }
474 
475 }

 总体来看这个类是继承了ImageView的基础上扩展了一些方法,主要是添加了能从服务器通过图片的Url来获取图片并缓存到本地的一系列的方法。

                               

既然是带下载功能的ImageView那么其中的setImageUrl(String url)和setImageUrl(String url, int position, ListView listView)肯定就是最主要的方法,其他应该是这两个方法实现过程中用的方法,那我们就以setImageUrl(String url)方法作为主线来分析这个类的实现。
1. 首先看第一个if...else...部分:
 1 if (mUrl != null && mUrl.equals(url) && (mCurrentlyGrabbedUrl == null ||
 2                 (mCurrentlyGrabbedUrl != null && !mCurrentlyGrabbedUrl.equals(url)))) {
 3             mFailure++;            
 4             if(mFailure > MAX_FAIMAX_FAILURESLURES){
 5                 Log.e(JamendoApplication.TAG, "Failed to download "+url+", falling back to default image");
 6                 loadDefaultImage();
 7                 return;
 8             }
 9         } else {
10             mUrl = url;
11             mFailure = 0;
12         }
第一次执行时mUrl还没有赋值初始化所以if的判断语句肯定为false肯定是先进入else部分,当后面图片因为一些原因下载失败需要重新下载的情况会首先进行if的判断语句如果为true则讲mFailure(下载失败次数)进行+1,
然后判断当mFailure>MAX_FAILURES(我们自己定义的下载失败最大次数)时调用loadDefaultImage()来加载默认的图片,loadDefaultImage()方法很简单就是把RemoteImageView设置显示之指定的默认图片。
2. 然后是updateCacheSize()方法
 1 public void updateCacheSize() {
 2         
 3         mPrevCacheSize = mCacheSize;        
 4         mCacheSize = Integer.parseInt(PreferenceManager
 5                 .getDefaultSharedPreferences(mContext).getString(
 6                         "cache_option", "100"));
 7         
 8         if(mPrevCacheSize!= 0 && mCacheSize == 0 ){
 9         //do it only once after changing mCacheSize value to 0
10             clearCache();
11         }
12 
13     }
从名字可以看出这个方法是更新缓存空间的大小。mPrevCacheSize代表之前设置的缓存大小,而mCacheSize是通过PreferenceManager从配置文件中读取的用户设置的缓存的大小,当且仅当用户将缓存空间大小设置为0时执行一次clearCache()方法来清理缓存;关于clearCache()就不详细分析了,大家自己看一下很简单,就是把程序设置在SD卡上用于缓存数据的文件夹内的文件删除清空。
clearCache()
 1 private void clearCache() {
 2         
 3         String extStorageDirectory = Environment.getExternalStorageDirectory()
 4                 .toString();
 5 
 6         String dirPath = extStorageDirectory + "/" + JAMENDO_DIR + "/dat0";
 7         File dir = new File(dirPath);
 8         File[] files = dir.listFiles();
 9 
10         if (files == null) {
11             // possible that sd card is not present/can't write
12             return;
13         }
14 
15         for (int i = 0; i < files.length; i++) {
16             files[i].delete();
17         }
18         
19     }

 

3. 最后也是一个if...else...结构。
判断当缓存空间mCacheSize大于0且url中包含ALBUMS("albums")或RADIOS("radios")时执行if块,否则执行else块。(至于为什么判断包含albums和radios是因为在SD卡上只缓存这两种图片)
 3.1首先看if段:
 1 if (mCacheSize>0 && (url.contains(ALBUMS) || url.contains(RADIOS))) {            
 2             String fileName = convertUrlToFileName(url);
 3             String dir = getDirectory(fileName);
 4             String pathFileName = dir + "/" + fileName;                        
 5             Bitmap tbmp = BitmapFactory.decodeFile(pathFileName);
 6             if (tbmp == null) {
 7                 Log.d(JamendoApplication.TAG, "Image is not present, try to download");
 8                 try{
 9                     new DownloadTask().execute(url);
10                 } catch (RejectedExecutionException e) {
11                     // do nothing, just don't crash
12                 }
13             } else {
14                 Log.i(JamendoApplication.TAG, "Loading album cover from file");
15                 this.setImageBitmap(tbmp);
16                 updateFileTime(dir,fileName );                
17             }
18             removeAlbumCoversCache(dir, fileName);
19             removeRadioCoversCache(dir, fileName);
20             
21         }
 3.1.1 用convertUrlToFileName(String url)方法从url中提取文件名filename,方法主要用了String中的replace方法,没什么可说的,看一下就行。
convertUrlToFileName(String url)
 1 private String convertUrlToFileName(String url) {
 2         String filename = url;
 3         filename = filename.replace("http://imgjam.com/", "");
 4         filename = filename.replace("/", ".");
 5         filename = filename.replace("jpg", "dat");
 6 
 7         // do filename complicated, hard to read by user while using sd
 8         if (filename.contains(ALBUMS)) {
 9             filename = filename.replace(ALBUMS, ALBUMS_CONV);
10         }
11         if (filename.contains(COVERS)) {
12             filename = filename.replace(COVERS, COVERS_CONV);
13         }
14         if (filename.contains(RADIOS)) {
15             filename = filename.replace(RADIOS, RADIOS_CONV);
16         }
17         
18         return filename;
19     }

 

 3.1.2 接着就是通过getDirectory(String filename)方法在获得或建立SD卡上的缓存路径并通过BitmapFactory.decodeFile(pathFileName)将文件解码变成位图。getDirectory()中的参数没有用到可能是开发者忘了去掉,方法中主要使用java中File类来获取或创建SD卡缓存路径,比较简单。
getDirectory
 1 private String getDirectory(String filename) {
 2 
 3         String extStorageDirectory = Environment.getExternalStorageDirectory()
 4                 .toString();
 5 
 6         String dirPath = extStorageDirectory + "/" + JAMENDO_DIR;
 7         File dirFile = new File(dirPath);
 8         dirFile.mkdirs();
 9 
10         dirPath = dirPath + "/dat0";
11         dirFile = new File(dirPath);
12         dirFile.mkdir();
13 
14         return dirPath;
15     }
3.1.3 在上面从sd卡获取到位图tbmp,判断tbmp是否为null,如果是的话就说明sd上没有这个图片缓存进而调用new DownloadTask().execute(url);去异步从服务器下载该图片,如果tbmp不为null则将tbmp显示,并更新改缓存的修改时间。这里面最重要的就是DownloadTask().execute(url)这个异步下载类,下面就看下这个方法的具体实现:
 1 /**
 2      * Asynchronous image download task
 3      * 
 4      * @author Lukasz Wisniewski
 5      */
 6     class DownloadTask extends AsyncTask<String, Void, String>{
 7         
 8         private String mTaskUrl;
 9         private Bitmap mBmp = null;
10 
11         @Override
12         public void onPreExecute() {
13             loadDefaultImage();
14             super.onPreExecute();
15         }
16 
17         @Override
18         public String doInBackground(String... params) {
19 
20             mTaskUrl = params[0];
21             InputStream stream = null;
22             URL imageUrl;
23             Bitmap bmp = null;
24 
25             try {
26                 imageUrl = new URL(mTaskUrl);
27                 try {
28                     stream = imageUrl.openStream();
29                     bmp = BitmapFactory.decodeStream(stream);
30                     try {
31                         if(bmp != null){
32                                 mBmp = bmp;
33                                 JamendoApplication.getInstance().getImageCache().put(mTaskUrl, bmp);
34                                 Log.d(JamendoApplication.TAG, "Image cached "+mTaskUrl);
35                             
36                         } else {
37                             Log.w(JamendoApplication.TAG, "Failed to cache "+mTaskUrl);
38                         }
39                     } catch (NullPointerException e) {
40                         Log.w(JamendoApplication.TAG, "Failed to cache "+mTaskUrl);
41                     }
42                 } catch (IOException e) {
43                     Log.w(JamendoApplication.TAG, "Couldn't load bitmap from url: " + mTaskUrl);
44                 } finally {
45                     try {
46                         if(stream != null){
47                             stream.close();
48                         }
49                     } catch (IOException e) {}
50                 }
51 
52             } catch (MalformedURLException e) {
53                 e.printStackTrace();
54             }
55             return mTaskUrl;
56         }
57 
58         @Override
59         public void onPostExecute(String url) {
60             super.onPostExecute(url);
61             
62             // target url may change while loading
63             if(!mTaskUrl.equals(mUrl))            {
64                 
65                 if(url.contains(ALBUMS) || url.contains(RADIOS) ){
66                     saveBmpToSd(mBmp, url);                    
67                 }
68                 return;
69             }
70             
71             
72             Bitmap bmp = JamendoApplication.getInstance().getImageCache().get(url);
73             if(bmp == null){
74                 Log.w(JamendoApplication.TAG, "Trying again to download " + url);
75                 RemoteImageView.this.setImageUrl(url);
76             } else {
77                 
78                 // if image belongs to a list update it only if it's visible
79                 if(mListView != null)
80                     if(mPosition < mListView.getFirstVisiblePosition() || mPosition > mListView.getLastVisiblePosition())
81                         return;
82                 
83                         
84                 RemoteImageView.this.setImageBitmap(bmp);                
85                 mCurrentlyGrabbedUrl = url;                
86                 if(url.contains(ALBUMS) || url.contains(RADIOS) ){                
87                     saveBmpToSd(mBmp, url);
88                 }                
89             }
90         }
91 
92     };
有关AsyncTask在android-jamendo源码学习(二)——HomeActivity 中已经介绍了,在这里就着重介绍这个内部类中的每个方法里的具体实现。
1. 首先是在onPreExecute()中调用loadDefaultImage()使页面在图片下载完成之前显示默认的图片。
2. 在doInBackground方法中 首先将传递进来的String类型的图片地址url通过imageUrl = new URL(mTaskUrl)转变成URL,然后通过URL的openStream()方法获取图片地址对应图片的输入流,接着用BitmapFactory.decodeStream(stream)将输入流转变成Bitmap。接着同过判断bitmap!=null来确定图片是否下载成功,下载成功的话就讲图片缓存到JamendoApplication.getInstance().getImageCache()这个WeakHashMap<String, Bitmap>若引用的hashmap中,WeakHashMap可以参看(转载)深入理解WeakHashmap 。最后在finally块中关闭输入流返回图片地址mTaskUrl。
3. onPostExecute(String url)方法,当doInBackground方法结束后即图片下载完成后的处理,首先是判断在下载过程中目标mUrl有没有改变,如果url改变了且url.contains(ALBUMS) || url.contains(RADIOS)为真则将的下载的图片通过saveBmpToSd(mBmp, url)以下载的url获取的文件名保存到SD卡上并退出方法。如果目标mUrl没有改变,则将从之前缓存到JamendoApplication.getInstance().getImageCache()中的图片取出来,如果取到的图片为空则重新调用RemoteImageView.this.setImageUrl(url)去获取图片,若不为空则将位图付给RemoteImageView显示并根据url.contains(ALBUMS) || url.contains(RADIOS)条件将图片保存到SD卡上。我们还看到这段代码:
1 // if image belongs to a list update it only if it's visible
2                 if(mListView != null)
3                     if(mPosition < mListView.getFirstVisiblePosition() || mPosition > mListView.getLastVisiblePosition())
4                         return;
它的作用是当图片是显示在listview中时判断该图片是否在显示范围内,如果不在就直接退出改方法。
到这里DownloadTask().execute(url)就介绍完了 我们回到3.1.3最后还有removeAlbumCoversCache(dir, fileName)和removeRadioCoversCache(dir, fileName);
1. 首先看removeAlbumCoversCache(dir, fileName)从名字可以看出他是要清理Ablum的缓存具体实现先看源码:
 1 private void removeAlbumCoversCache(String dirPath, String filename) {
 2 
 3         if (!filename.contains(ALBUM_COVER_MARKER)) {
 4             return;
 5 
 6         }
 7 
 8         File dir = new File(dirPath);
 9         File[] files = dir.listFiles();
10 
11         if (files == null) {
12             // possible sd card is not present/cant write
13             return;
14         }
15 
16         int dirSize = 0;
17 
18         for (int i = 0; i < files.length; i++) {
19             if (files[i].getName().contains(ALBUM_COVER_MARKER)) {
20                 dirSize += files[i].length();
21             }
22         }
23 
24         
25         
26         if (dirSize > mCacheSize * MB || FREE_SD_SPACE_NEEDED_TO_CACHE > freeSpaceOnSd()) {
27             int removeFactor = (int) ((0.4 * files.length) + 1);
28             Arrays.sort(files, new FileLastModifSort());
29             Log.i(JamendoApplication.TAG, "Clear some album covers cache files ");
30             for (int i = 0; i < removeFactor; i++) {
31                 if (files[i].getName().contains(ALBUM_COVER_MARKER)) {
32                     files[i].delete();                
33                 }
34             }
35         }
36 
37     }

 

 首先判断filename中是否包含ALBUM_COVER_MARKER(1.500)若包含则进行后面的处理,否则直接return退出。经过调试观察发现图片的名字中有1.500、1.300、1.100的字段,数字越大缓存文件越大,就是说分别代表着不同大小类型的图片。对于Ablum图片是要显示在播放页面的比较大的图片所以后面采用了统计其文件总和是否超过所设置的缓存size(dirSize > mCacheSize * MB)并判断缓存的可用空间freeSpaceOnSd()是否满足预设的最小空间FREE_SD_SPACE_NEEDED_TO_CACHE(程序中是1.500,经调试发现现在应该是1.300),如果两个有一个不满足就对对缓存文件夹进行清理,清理的数量为目录下ablum文件数目的40%+1((0.4 * files.length) + 1),加一是因为计算结果在强转成int型时会舍去小数点后的值,+1可以保证最后的结果不会小于ablum文件数目的40% 。最后删除那一部分缓存。
2.在看removeRadioCoversCache(String dirPath, String filename) 主要是清理列表先试用的较小的缓存图片。先看源代码:
 1 private void removeRadioCoversCache(String dirPath, String filename) {
 2 
 3         if (filename.contains(ALBUM_COVER_MARKER)) {
 4             return;
 5         }
 6 
 7         File file = new File(dirPath, filename);
 8         if (file.lastModified() != 0
 9                 && System.currentTimeMillis() - file.lastModified() > mTimeDiff) {
10             
11                         
12             Log.i(JamendoApplication.TAG, "Clear some album or radio thumbnail cache files ");
13             file.delete();
14         }
15 
16     }
通过这个filename.contains(ALBUM_COVER_MARKER)判断来清理较小的缓存图片,因为图片较小,对缓存空间影响不大多以采用根据文件的最后使用时间来处理,当最后使用日期距离现在的日期(System.currentTimeMillis() - file.lastModified())超过指定时间(mTimeDiff)就删除该缓存文件。
到此3.1的if段就完了。

3.2   else部分,先给出源码:

 1 else {
 2             Log.i(JamendoApplication.TAG, "File not cached supported" + url);
 3             ImageCache imageCache = JamendoApplication.getInstance()
 4                     .getImageCache();
 5             if (imageCache.isCached(url)) {                
 6                 this.setImageBitmap(imageCache.get(url));
 7             } else {
 8                 try {
 9                     Log.i(JamendoApplication.TAG, "Image is not present, try to download");
10                     new DownloadTask().execute(url);
11                 } catch (RejectedExecutionException e) {
12                     // do nothing, just don't crash
13                 }
14             }
15         }

 

 else这一部分是用来处理不需要保存的到SD卡上的图片的,首先从JamendoApplication中取出存放缓存图片的map getImageCache()然后通过以url为key值判断缓存中是否有该图片(imageCache.isCached(url)),若有则直接显示,若没有就调用DownloadTask().execute(url)去异步下载该图片。

到此整个RemoteImageView就介绍完了~~~大家多多指正~~~~

休息~休息一下~~

 

 

posted @ 2013-01-17 00:45  若水恋冰  阅读(1432)  评论(4编辑  收藏  举报