android-jamendo源码学习之ImageView扩展类——RemoteImageView
精彩继续~~在 android-jamendo源码学习(二)——HomeActivity中我们遇到了RemoteImageView,一个自定义的可以从服务器下载图片的控件。后面肯定还会用到,所以拿出来在这里分析下这个控件。
首先给出源代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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卡上用于缓存数据的文件夹内的文件删除清空。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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方法,没什么可说的,看一下就行。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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卡缓存路径,比较简单。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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就介绍完了~~~大家多多指正~~~~
休息~休息一下~~
我就是我,独一无二。………………【LuckyStar】◤若水恋冰◢ @:zc.luckystar@gmail.com