天天看點

圖檔處理架構之ImageLoader

一 前言

      剛開始作android項目時使用就是 ImageLoader來加載圖檔的,在其内部自動實作了圖檔的下載下傳、緩存等功能,自己隻需要配置 一下 緩存路徑就可以,當時感覺這已經很牛掰了,現在己經出現了Glide、Picasso等圖檔處理架構,這些架構使用起來更加友善可靠, 不過在很多的老項目中還有很多在使用 ImageLoader, 在此總結下,開源庫:https://github.com/nostra13/Android-Universal-Image-Loader,也可以到我的資源中直接下載下傳Jar包(點選下載下傳 ImageLoader )放到項目的libs目錄下,然後右鍵選擇Add As Library, 在gradle檔案中有如下代碼:

compile files('libs/universal-image-loader-1.9.4-with-sources.jar')      

說明你添加庫成功。

二 配置

      配置 ImageLoader需要在啟動App的時候就要進行配置,也就是說需要在Application的子類中進行配置,你得自定義一個類繼承 Application,在該類的onCreate函數中配置 ImageLoader,當然該類( Application的子類 )必須在AndroidManifest.xml檔案中進行注冊,如我的是MyApplication,注冊如下:

<application
    android:name=".MyApplication"
    ...>
    ......
</application>      

配置代碼如下:

@Override
public void onCreate() {
    super.onCreate();
    initImageLoader(this);
}

public static void initImageLoader(Context context ){
    //FileUtil.getAppCacheAbsoluteFile(context) 用來建立緩存檔案
    DiskCache cache = new UnlimitedDiskCache(FileUtil.getAppCacheAbsoluteFile(context));
    //ImageUtil.PATH_USER_IMAGE為檔案路徑
    ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(context)
            .memoryCacheExtraOptions(480, 800) // max width, max height,即儲存的每個緩存檔案的最大長寬
            .threadPoolSize(3) //線程池内線程的數量
            .threadPriority(Thread.NORM_PRIORITY - 2)
            .denyCacheImageMultipleSizesInMemory()
            .diskCacheFileNameGenerator(new Md5FileNameGenerator()) //将儲存的時候的URI名稱用MD5 加密
            .memoryCache(new UsingFreqLimitedMemoryCache(2 * 1024 * 1024))
            .memoryCacheSize(2 * 1024 * 1024) // 記憶體緩存的最大值
            .diskCacheSize(50 * 1024 * 1024)  // SD卡緩存的最大值
            .tasksProcessingOrder(QueueProcessingType.LIFO)
            // 由原先的discCache -> diskCache
            .diskCache(cache)//自定義緩存路徑
            .imageDownloader(new BaseImageDownloader(context, 5 * 1000, 30 * 1000)) // connectTimeout (5 s), readTimeout (30 s)逾時時間
            .writeDebugLogs() // Remove for release app
            .build();
    //全局初始化此配置
    ImageLoader.getInstance().init(config);
}
      

三 加載圖檔

1 直接加載

ImageLoader.getInstance().displayImage("http://img2.pconline.com.cn/pconline/0706/19/1038447_34.jpg",imageView3);      

2 設定占位圖和加載失敗的圖檔

DisplayImageOptions displayImageOptions = new DisplayImageOptions.Builder()
        .cacheInMemory(true)
        .cacheOnDisk(true)
        .showImageOnFail(R.mipmap.ic_launcher)
        .showImageOnLoading(R.mipmap.ic_launcher)
        .build();
ImageLoader.getInstance().displayImage("http://img2.pconline.com.cn/pconline/0706/19/1038447_34.jpg"
        ,imageView3,displayImageOptions);
      

3 設定監聽     ImageLoader提供了螢幕,可以對圖檔加載的過程進行監聽

ImageLoader.getInstance().displayImage("http://img2.pconline.com.cn/pconline/0706/19/1038447_34.jpg"
        , imageView3, new ImageLoadingListener() {
            @Override
            public void onLoadingStarted(String s, View view) {
                //開始下載下傳圖檔
            }

            @Override
            public void onLoadingFailed(String s, View view, FailReason failReason) {
                //下載下傳失敗
            }

            @Override
            public void onLoadingComplete(String s, View view, Bitmap bitmap) {
                //下載下傳完成

            }

            @Override
            public void onLoadingCancelled(String s, View view) {
                //下載下傳失敗

            }
        });
      

說明,同時 ImageLoader也提loaderImage用來加載圖檔,如下:

public void loadImage(String uri, ImageLoadingListener listener) {
    this.loadImage(uri, (ImageSize)null, (DisplayImageOptions)null, listener, (ImageLoadingProgressListener)null);
}

public void loadImage(String uri, ImageSize targetImageSize, ImageLoadingListener listener) {
    this.loadImage(uri, targetImageSize, (DisplayImageOptions)null, listener, (ImageLoadingProgressListener)null);
}

public void loadImage(String uri, DisplayImageOptions options, ImageLoadingListener listener) {
    this.loadImage(uri, (ImageSize)null, options, listener, (ImageLoadingProgressListener)null);
}

public void loadImage(String uri, ImageSize targetImageSize, DisplayImageOptions options, ImageLoadingListener listener) {
    this.loadImage(uri, targetImageSize, options, listener, (ImageLoadingProgressListener)null);
}

public void loadImage(String uri, ImageSize targetImageSize, DisplayImageOptions options, ImageLoadingListener listener, ImageLoadingProgressListener progressListener) {
    this.checkConfiguration();
    if(targetImageSize == null) {
        targetImageSize = this.configuration.getMaxImageSize();
    }

    if(options == null) {
        options = this.configuration.defaultDisplayImageOptions;
    }

    NonViewAware imageAware = new NonViewAware(uri, targetImageSize, ViewScaleType.CROP);
    this.displayImage(uri, (ImageAware)imageAware, options, listener, progressListener);
}
      

從上面可以看出這就要你自己去處理結果了,當然Image Loader也可以從本地、assets、drawable、content加載圖檔,如下: 本地:

/**
 * 從記憶體卡中異步加載本地圖檔
 *
 * @param uri 圖檔的絕對路徑
 * @param imageView 需要顯示圖檔的ImageView對象
 * @param options 顯示配置
 */
public  void displayFromSDCard(String uri, ImageView imageView , DisplayImageOptions options ) {
    ImageLoader.getInstance().displayImage("file://" + uri, imageView, options);
}      

assets:

public void dispalyFromAssets(String imageName, ImageView imageView ,DisplayImageOptions options) {
    // String imageUri = "assets://image.png"; // from assets
    ImageLoader.getInstance().displayImage("assets://" + imageName, imageView ,options);
}      

drawable:

public void displayFromDrawable(int imageId, ImageView imageView ,DisplayImageOptions options) {
    // String imageUri = "drawable://" + R.drawable.image; // from drawables
    // (only images, non-9patch)
    ImageLoader.getInstance().displayImage("drawable://" + imageId, imageView, options);
}
      

content:

public void displayFromContent(String uri, ImageView imageView,DisplayImageOptions options) {
    ImageLoader.getInstance().displayImage("content://" + uri, imageView, options);
}
      

我把這些常用的方法放到工具類ImageLoaderUtil(代碼點選檢視)中。