圖片加載框架--ImageLoader實現(二)


前言

上篇簡單介紹了UniversalImageLoader的使用,分析了下源代碼,大致可以進行如下划分,本文將分析圖片加載的Imageloader實現,。

正文

通過ImageLoader實例對象,調用public void displayImage(String uri, ImageView imageView, DisplayImageOptions options, ImageLoadingListener listener)發放將開始加載圖片,具體過程可以分為幾個階段:

 合法性檢查

主要是初始化檢查和參數檢查,可能會拋出異常或是下載不受干擾可以繼續;有傳入的圖片地址為空,imageview為空,圖片配置實例為空,過程監聽接口為空四種情況。

if (configuration == null) { 
    throw new RuntimeException(ERROR_NOT_INIT); 
} 
if (imageView == null) { 
    Log.w(TAG, ERROR_WRONG_ARGUMENTS); 
    return; 
} 
if (listener == null) { 
    listener = emptyListener; 
} 
if (options == null) { 
    options = configuration.defaultDisplayImageOptions; 
}

if (uri == null || uri.length() == 0) { 
    cacheKeyForImageView.remove(imageView); 
    listener.onLoadingStarted(); 
    if (options.isShowImageForEmptyUri()) { 
        imageView.setImageResource(options.getImageForEmptyUri()); 
    } else { 
        imageView.setImageBitmap(null); 
    } 
    listener.onLoadingComplete(null); 
    return; 
} 

 


如果沒有初始化ImageLoader是比較嚴重的,將直接拋出運行時異常,控件ImageView為空時不影響,可以直接退出,不再下載,圖片配置和監聽接口為空則將啟用默認值,至於圖片url的話,由於初始化時已經實例化了默認值的情形,所以將顯示本地設置的默認圖片,同時將控件移出HashMap。

 

加載准備

這里的准備操作一個是獲取圖片的尺寸參數,然后根據這個參數和url生成標記ImageView的key,最后以key-value的形式存入HashMap中備用,

targetSize = getImageSizeScaleTo(imageView); 
String memoryCacheKey = MemoryCacheKeyUtil.generateKey(uri, targetSize); 
cacheKeyForImageView.put(imageView, memoryCacheKey); 

加載操作

加載分為調用內存緩存和本地緩存/網絡下載,根據上一步加載准備中得到的key獲取bitmap,這個過程比較發雜,單獨介紹。

if (bmp != null && !bmp.isRecycled()) { 
if (configuration.loggingEnabled) Log.i(TAG, String.format(LOG_LOAD_IMAGE_FROM_MEMORY_CACHE, memoryCacheKey)); 
listener.onLoadingStarted(); 
Bitmap displayedBitmap = options.getDisplayer().display(bmp, imageView); 
imageView.setImageBitmap(displayedBitmap); 
listener.onLoadingComplete(bmp); 
}

 

根據得到的bitmap,如果不為空且未被標記為回收狀態,那么就可以使用這個緩存的bitmap,調用監聽接口的onLoadingStarted()處理一些加載錢的操作,然后對bitmap做一些顯示前的操作,這個就用到傳入進來的圖片顯示的option配置,如果沒傳這個值,那啟用默認值,應該是不對bitmap操作,這個默認的option使用SimpleBitmapDisplayer 實例,查看其源代碼,果然,是直接將bitmap設置給ImageView然后對外返回原來的Bitmap,對於這種情況后面的在此設置bitmap給imageview其實有些累贅,重復操作了。

public final class SimpleBitmapDisplayer implements BitmapDisplayer { 
    @Override 
    public Bitmap display(Bitmap bitmap, ImageView imageView) { 
        imageView.setImageBitmap(bitmap); 
        return bitmap; 
    } 
}

接下來調用監聽接口的onLoadingComlete();到顯示內存緩存圖片的操作就結束了,下面介紹第二種情況,就是從磁盤緩存/網新下載圖片。

先調用監聽接口的onLoadingStarted();接着顯示一個下載過程中的圖片或則干脆在下載時不顯示任何圖片。接着檢查一下線程池是否初始化並正常工作中checkExecutors(),查看源代碼可以發現,項目用與下載的的task其實是通過ExecutorService來管理,如果還不知道什么是ExecutorService趕緊去補一下java的多線程並發編程吧。忍者

private void checkExecutors() { 
    if (imageLoadingExecutor == null || imageLoadingExecutor.isShutdown()) { 
        imageLoadingExecutor = Executors.newFixedThreadPool(configuration.threadPoolSize, configuration.displayImageThreadFactory); 
    } 
    if (cachedImageLoadingExecutor == null || cachedImageLoadingExecutor.isShutdown()) { 
        cachedImageLoadingExecutor = Executors.newFixedThreadPool(configuration.threadPoolSize, configuration.displayImageThreadFactory); 
    } 
} 

 

為了下載圖片這里把必要的圖片信息做了一個封裝傳給工作線程。ImageLoadingInfo imageLoadingInfo = new ImageLoadingInfo(uri, imageView, targetSize, options, listener, getLockForUri(uri));

現在一起看一下他的工作線程是怎么寫的。LoadAndDisplayImageTask displayImageTask = new LoadAndDisplayImageTask(configuration, imageLoadingInfo, new Handler());

這里的最后一個參數是我們熟悉的Handler 實例,可以預測這個task類應該是Runnale的是子類,在run()中根據情況向handler發送處理操作請求。(未完待續)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM