【UIL框架】Universal-Image-Loader完全解析(一)之介紹與使用詳解

weixin_34290000發表於2015-12-31

****(一).前言: ****
已經半個月沒有更新文章了,一方面是最近工作比較忙,另一方面我也在選擇部落格的題材。這次我主要講解平時用的比較多的圖片載入框架ImageLoader。雖然這個框架前不久作者已經停止更新了,不過這個圖片載入框架我已經用了很久了。我深知框架使用簡便是一方面,但是如果能夠不僅會使用而且能夠深知其中實現的原理才是最重要的。所以我把ImageLoader專案所有的程式碼閱讀了一遍並且給每個類和相關方法新增了中文版本的註釋。
本例以及UIL框架全部中文版本註釋專案已經更新到github,有興趣大家可以去clone,start或者fork。
地址https://github.com/jiangqqlmj/Android-Universal-Image-Loader-Modify
[順便說一下,可以微信掃描關注左側的二維碼關注訂閱號,獲取最新文章哈~]
本次專題的文章主要會涉及到以下部分ImageLoader的介紹和使用,部分重要模組分析以及相關原始碼講解。今天我們主要進行第一部分的講解(ImageLoader基礎介紹和使用講解)。
****(二).ImageLoader基本介紹: ****
我們在開發APP的時候肯定遇到載入圖片的需求尤其是列表需要載入大量圖片的時候,那麼我們勢必需要進行下載圖片並且進行顯示。但是由於記憶體等各方面的問題多多少少會遇到一些問題;例如:列表載入圖片,圖片錯亂分佈啦。或者出現OOM問題啦~~這時候我們需要開發圖片非同步載入並且可以適當壓縮框架。例如:UIL(Universal-Image-Loader,github專案地址UIL專案地址)除此之外還有其他很多框架Glide,Fresco,Picasso等等很多。後面幾個現在用的比較多而且還在更多。後面的文章我這邊也會分享其他的圖片載入框架。
UIL(Universal-Image-Loader)旨在提供一個強大的、靈活的和高度可定製的工具影象載入、快取和顯示功能。並且提供了許多配置選項和良好控制影象載入和快取的過程。所以在之前長久的一段時間裡,該框架的使用非常廣且很方便哦。
UIL框架特點:
1.支援多執行緒圖片載入(同步或者非同步)
2.支援自定義配置ImageLoader,例如執行緒池,圖片下載器,記憶體快取策略,硬碟快取策略,圖片顯示選項以及其他的一些配置
3.支援自定義配置圖片顯示,例如:快取開關選擇,介面選項,圖片載入進度以及顯示
4.支援圖片記憶體快取或者檔案系統,裝置SD快取
5.支援圖片載入進度監聽(包括圖片下載進度監聽)
6.支援框架更多工具類的擴充套件
7.同樣可以支援例如ListView,GridView進行滑動的時候暫停或者恢復圖片載入顯示等功能。
8.當然還有其他很過特點,具體大家讀了原始碼就會知道啦….
****(三).ImageLoader快速安裝: ****
如果我們要使用ImageLoader大家都可以專案地址下載一份程式碼其中會有imageLoader的jar包引入到專案就可以了。整體專案中內容資料夾如下:

1135855-7cac9f6ea48d12c3.png
1.png

3.1.我們下載imageloader的jar包到我們專案libs資料夾中,然後關聯即可(universal-image-loader-1.9.5.jar):
3.2.現在我們採用Android Studio開發專案了,我們只需要build.gradle中新增以下依賴即可:

compile'com.nostra13.universalimageloader:universal-image-loader:1.9.5'

3.3.專案配置檔案需要新增相關許可權(主要為訪問網路許可權,如果圖片需要sdcard快取還需要多新增一個許可權)

<manifest>
    <!-- Include following permission if you load images from Internet -->
    <uses-permission android:name="android.permission.INTERNET" />
    <!-- Include following permission if you want to cache images on SD card -->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    ...
</manifest>

3.4.最後我們需要在第一次使用ImageLoader之前,做一下ImageLoader的基礎配置,該項配置可以在application或者activity中做即可,如下方式:

   ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(this)
            ...
            .build();
        ImageLoader.getInstance().init(config);

3.5.下面我們就可以具體使用ImageLoader來進行載入和顯示圖片啦。
****(四).ImageLoader全域性配置項(Configuration)****
上面3.4中我們講到了ImageLoader在使用之前需要進行全域性配置一下。OK,ImageLoader給我們提供了一個ImageLoaderConfiguration來進行全域性設定ImageLoader。不過該設定是全域性的,我們只需要設定一次即可了。
檢視ImageLoader文件以及ImageLoaderConfiguration原始碼發現,該為我們提供了所有的配置項都是可選的。除非你需要自定義設定,模板我們可以呼叫該其中預設構造的方法如下:

 ImageLoaderConfiguration configuration=ImageLoaderConfiguration.createDefault(this);
       ImageLoader.getInstance().init(configuration);

上面的createDefault方法會給我們預設初始化一些配置項,具體所有配置可選項如下圖:


1135855-89b090f0ca83474f.png
2.png

上面包括設定快取大小,任務執行器,執行緒池執行緒數量,執行緒權重,任務執行演算法,磁碟快取大小,快取檔案數量,快取檔案命名規則,圖片下載器,解碼器,圖片顯示配置項等等。大家可以隨意根據專案實際情況配置即可了。
****(五).ImageLoader圖片Display配置項(Display Options)****
上面我們講到了ImageLoader的全域性配置,在對於圖片顯示的時候(ImageLoader.displayImage(…)的時候),我們還可以設定圖片顯示的引數(主要使用DisplayImageOptions)。Display Options(顯示可選項)用於每次圖片顯示任務的時候(ImageLoader.displayImage()該方法被呼叫)。
【注意】如果我們沒有設定圖片顯示配置項,那麼我在顯示圖片的時候會預設呼叫圖片預設顯示方式。具體可選配置項如下:


1135855-2afeee025ab96f15.png
3.png

上面包括圖片載入過程中,圖片地址為空以及圖片載入失敗的圖片,載入延時,開啟記憶體快取以及磁碟快取,圖片縮放型別,圖片編碼型別以及圖片顯示載入器等等引數。具體根據實際專案選擇配置即可。
****(六).ImageLoader載入圖片講解****

現在我們開始講解使用ImageLoader載入圖片啦,在這之前大家一定要按照第三點的內容ImageLoader要安裝一下以及做一下基本許可權以及全域性配置哦~下面我們首先看一下ImageLoader來顯示圖片的幾個方法:


1135855-217513b0c9b15496.png
4.png

檢視上面ImageLoader的方法圖看:主要分為下面三種方式載入圖片啦~我們在專案中一般使用前兩種哦(displayImage和loadImage),因為這兩種是非同步的,另外的loadImageSync是同步的啦。
6.1.dispalyImage()方法使用講解:
6.1.1本例中我ImageLoader全域性是採用預設配置的如下:
public class UILApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        initImageLoader();
    }
    private void initImageLoader(){
        ImageLoaderConfiguration configuration=ImageLoaderConfiguration.createDefault(this);
        ImageLoader.getInstance().init(configuration);
    }
}

例項佈局檔案如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    androidlayout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:gravity="center">
    <ImageView
        android:id="@+id/test_img_one"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/ic_data_loading"/>
</LinearLayout>

然後Activitity例項化控制元件以及ImageLoader,呼叫displayImage方法即可:

 ImageView test_img_one=(ImageView)this.findViewById(R.id.test_img_one);
 ImageLoader.getInstance().displayImage(ImageDataUtils.ImagesUtils[0],test_img_one);

6.1.2.上邊我們採用displayImage是兩個引數的方法,我們同時可以在這邊加入圖片顯示引數配置如下即可:

ImageView test_img_one=(ImageView)this.findViewById(R.id.test_img_one);
        DisplayImageOptions options=new DisplayImageOptions.Builder()
                .showImageOnLoading(R.drawable.ic_data_loading)
                .showImageOnFail(R.drawable.ic_data_error)
                .cacheInMemory(true)
                .cacheOnDisk(true)
                .build();
ImageLoader.getInstance().displayImage(ImageDataUtils.ImagesUtils[1],test_img_one,options);

上面我們配置載入過程中和載入失敗顯示的圖片以及開啟記憶體和磁碟快取功能執行效果如下:


1135855-7340c3a607948ce1.gif
5.gif

6.1.3.在顯示的時候我們還可以加入圖片的目標尺寸,如下:

ImageSize size=new ImageSize(100,50);
ImageLoader.getInstance().displayImage(ImageDataUtils.ImagesUtils[1],test_img_one,size);

這邊構造一個ImageSize物件來定義目標圖片的寬度和高度,傳入寬100,高50,執行效果如下:


1135855-9380f0c354c08d0b.png
6.png

6.1.4.除了上面的三個顯示過載方法之外,我們還可以傳入一個圖片載入進度監聽器進入,具體介面回撥我們放入到下面loadImage()方法中講解。
6.2.loadImage()方法使用講解:
上面6.1我們已經對displayImage()方法做了一些講解,現在我們對於另外一個非同步載入圖片方法loadImage做一下講解。本例中我這邊採用TwoActivity以及一個簡單佈局:該佈局中就放入一個ImageView即可。全域性配置和上面一樣。
6.2.1.loadImage(Stringuri, ImageLoadingListener listener)
該傳入兩個引數第一個為圖片下載地址,第二個為圖片載入監聽器首先採用預設的介面如下設定:

ImageView test_img_two=(ImageView)this.findViewById(R.id.test_img_two);
        ImageLoader.getInstance().loadImage(ImageDataUtils.ImagesUtils[3], new ImageLoadingListener() {
            @Override
            public void onLoadingStarted(String imageUri, View view) {
                //圖片開始載入的時候呼叫
                Log.d("zttjiangqq","onLoadingStarted...");
            }
            @Override
            public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
                //圖片載入失敗呼叫
                Log.d("zttjiangqq","onLoadingFailed...");
            }
            @Override
            public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
                //圖片載入完成呼叫
                Log.d("zttjiangqq","onLoadingComplete...");
                test_img_two.setImageBitmap(loadedImage);
            }
            @Override
            public void onLoadingCancelled(String imageUri, View view) {
                //圖片載入取消呼叫
                Log.d("zttjiangqq","onLoadingCancelled...");
            }
        });

具體執行列印的日誌和執行結果如下:


1135855-245ea779bb871293.png
7.png

1135855-071a8bfacf3a891d.png
8.png

我們看到使用ImageLoadingListener介面必須要實現介面中四個方法,但是我們平時實際情況下可能不需要回撥那麼多方法,不錯的是UIL給我們提供了一個類SimpleImageLoadingListener類,該類實現了ImageLoadingListener介面。我們傳入該實現類即可,這樣我們重寫實際所需的方法就方便多了。具體例項如下

 ImageLoader.getInstance().loadImage(ImageDataUtils.ImagesUtils[4],new SimpleImageLoadingListener(){
            @Override
            public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
                super.onLoadingComplete(imageUri, view, loadedImage);
                //圖片載入完成時候呼叫
                Log.d("zttjiangqq","onLoadingComplete...");
                test_img_two.setImageBitmap(loadedImage);
            }
            @Override
            public void onLoadingStarted(String imageUri, View view) {
                super.onLoadingStarted(imageUri, view);
                //圖片開始載入的時候呼叫
                Log.d("zttjiangqq", "onLoadingStarted...");
            }
        });

這邊我只重寫了onLoadingComplete和onLoadingStarted兩個方法,程式碼量上面就減少了很多。
6.2.2.loadImage(Stringuri, ImageSize targetImageSize, DisplayImageOptions options,ImageLoadingListenerlistener)
該載入圖片方法6.1中講得差不多,我們同時可以傳入圖片顯示配置項,具體示例如下:

 DisplayImageOptions options=new DisplayImageOptions.Builder()
                .showImageOnLoading(R.drawable.ic_data_loading)
                .showImageOnFail(R.drawable.ic_data_error)
                .cacheInMemory(true)
                .cacheOnDisk(true)
                .build();
        ImageLoader.getInstance().loadImage(ImageDataUtils.ImagesUtils[5],options,new SimpleImageLoadingListener(){
            @Override
            public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
                super.onLoadingComplete(imageUri, view, loadedImage);
                //圖片載入完成時候呼叫
                Log.d("zttjiangqq","onLoadingComplete...");
                test_img_two.setImageBitmap(loadedImage);
            }
        });

6.2.3.loadImage(Stringuri, ImageSize targetImageSize, ImageLoadingListener listener)
該載入圖片方式我們可以傳入目標圖片的尺寸大小,用起來直接構造一個ImageSize傳入進去就可以了。具體方法如下:

ImageSize size=new ImageSize(100,50);
        ImageLoader.getInstance().loadImage(ImageDataUtils.ImagesUtils[6],size,new SimpleImageLoadingListener(){
            @Override
            public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
                super.onLoadingComplete(imageUri, view, loadedImage);
                  //圖片載入完成時候呼叫
                  Log.d("zttjiangqq","onLoadingComplete...");
                  test_img_two.setImageBitmap(loadedImage);
            }
        });

6.2.4.主要就是以上幾種方式,其他的圖片載入方法和以上的差不多,只需要傳入對應的引數就可以了。
(七).最後總結
今天我們對於UIL(Universal-Image-Loader)開源框架的介紹和基本使用做了相關講解,包括介紹,安裝,配置以及基本使用方面。下一講會著重講解該開源元件幾個核心的類以及相關使用注意事項。
本例以及UIL框架全部中文版本註釋專案已經更新到github,有興趣大家可以去clone,start或者fork。
地址https://github.com/jiangqqlmj/Android-Universal-Image-Loader-Modify

關注我的訂閱號(codedev123),每天分享移動開發技術(Android/IOS),專案管理以及部落格文章!(歡迎關注,第一時間推送精彩文章)


1135855-0c7847b2d643aabf.jpg
qrcode_for_gh_c6208faa1f42_258.jpg

相關文章