ImageLoader簡單使用


新建一個MyApplication繼承Application,並在onCreate()中創建ImageLoader的配置參數,並初始化到ImageLoader中代碼如下

 1 package com.example.uil;
 2 
 3 import com.nostra13.universalimageloader.core.ImageLoader;
 4 import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
 5 
 6 import android.app.Application;
 7 
 8 public class MyApplication extends Application {
 9 
10     @Override
11     public void onCreate() {
12         super.onCreate();
13 
14         //創建默認的ImageLoader配置參數
15         ImageLoaderConfiguration configuration = ImageLoaderConfiguration
16                 .createDefault(this);
17 
18         //Initialize ImageLoader with configuration.
19         ImageLoader.getInstance().init(configuration);
20     }
21 
22 }

ImageLoaderConfiguration是圖片加載器ImageLoader的配置參數,使用了建造者模式,這里是直接使用了 createDefault()方法創建一個默認的ImageLoaderConfiguration,當然我們還可以自己設置 ImageLoaderConfiguration,設置如下

 1 //緩存文件夾
 2 File cacheDir = StorageUtils.getOwnCacheDirectory(getApplicationContext(), "imageloader/Cache");
 3 File cacheDir = StorageUtils.getCacheDirectory(context);  //緩存文件夾路徑
 4         ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(context)
 5                 .memoryCacheExtraOptions(480, 800) // default = device screen dimensions 內存緩存文件的最大長寬
 6                 .diskCacheExtraOptions(480, 800, null)  // 本地緩存的詳細信息(緩存的最大長寬),最好不要設置這個
 7                 .taskExecutor(...)
 8                 .taskExecutorForCachedImages(...)
 9                 .threadPoolSize(3) // default  線程池內加載的數量
10                 .threadPriority(Thread.NORM_PRIORITY - 2) // default 設置當前線程的優先級
11                 .tasksProcessingOrder(QueueProcessingType.FIFO) // default
12                 .denyCacheImageMultipleSizesInMemory()
13                 .memoryCache(new LruMemoryCache(2 * 1024 * 1024)) //可以通過自己的內存緩存實現
14                 .memoryCacheSize(2 * 1024 * 1024)  // 內存緩存的最大值
15                 .memoryCacheSizePercentage(13) // default
16                 .diskCache(new UnlimitedDiscCache(cacheDir)) // default 可以自定義緩存路徑 
17                 .diskCacheSize(50 * 1024 * 1024) // 50 Mb sd卡(本地)緩存的最大值
18                 .diskCacheFileCount(100)  // 可以緩存的文件數量
19                 // default為使用HASHCODE對UIL進行加密命名, 還可以用MD5(new Md5FileNameGenerator())加密
20                 .diskCacheFileNameGenerator(new HashCodeFileNameGenerator())
21                 .imageDownloader(new BaseImageDownloader(context)) // default
22                 .imageDecoder(new BaseImageDecoder()) // default
23                 .defaultDisplayImageOptions(DisplayImageOptions.createSimple()) // default
24                 .writeDebugLogs() // 打印debug log
25                 .build(); //開始構建

上面的這些就是所有的選項配置,我們在項目中不需要每一個都自己設置,一般使用createDefault()創建的 ImageLoaderConfiguration就能使用,然后調用ImageLoader的init()方法將 ImageLoaderConfiguration參數傳遞進去,ImageLoader使用單例模式。

1 <manifest>
2     <uses-permission android:name="android.permission.INTERNET" />
3     <!-- Include next permission if you want to allow UIL to cache images on SD card -->
4     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
5     ...
6     <application android:name="MyApplication">
7         ...
8     </application>
9 </manifest>

接下來我們就可以來加載圖片了,首先我們定義好Activity的布局文件

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3     android:layout_width="fill_parent"
 4     android:layout_height="fill_parent">
 5 
 6     <ImageView
 7         android:layout_gravity="center"
 8         android:id="@+id/image"
 9         android:src="@drawable/ic_empty"
10         android:layout_width="wrap_content"
11         android:layout_height="wrap_content" />
12 
13 </FrameLayout>
里面只有一個ImageView,很簡單,接下來我們就去加載圖片,我們會發現ImageLader提供了幾個圖片加載的方法,主要是這幾個 displayImage(), loadImage(),loadImageSync(),loadImageSync()方法是同步 的,android4.0有個特性,網絡操作不能在主線程,所以loadImageSync()方法我們就不去使用
loadimage()加載圖片
我們先使用ImageLoader的loadImage()方法來加載網絡圖片
 1 final ImageView mImageView = (ImageView) findViewById(R.id.image);
 2         String imageUrl = "https://lh6.googleusercontent.com/-55osAWw3x0Q/URquUtcFr5I/AAAAAAAAAbs/rWlj1RUKrYI/s1024/A%252520Photographer.jpg";
 3 
 4         ImageLoader.getInstance().loadImage(imageUrl, new ImageLoadingListener() {
 5 
 6             @Override
 7             public void onLoadingStarted(String imageUri, View view) {
 8 
 9             }
10 
11             @Override
12             public void onLoadingFailed(String imageUri, View view,
13                     FailReason failReason) {
14 
15             }
16 
17             @Override
18             public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
19                 mImageView.setImageBitmap(loadedImage);
20             }
21 
22             @Override
23             public void onLoadingCancelled(String imageUri, View view) {
24 
25             }
26         });
27 傳入圖片的url和ImageLoaderListener, 在回調方法onLoadingComplete()中將loadedImage設置到ImageView上面就行了,如果你覺得傳入 ImageLoaderListener太復雜了,我們可以使用SimpleImageLoadingListener類,該類提供了 ImageLoaderListener接口方法的空實現,使用的是缺省適配器模式
28 final ImageView mImageView = (ImageView) findViewById(R.id.image);
29         String imageUrl = "https://lh6.googleusercontent.com/-55osAWw3x0Q/URquUtcFr5I/AAAAAAAAAbs/rWlj1RUKrYI/s1024/A%252520Photographer.jpg";
30 
31         ImageLoader.getInstance().loadImage(imageUrl, new SimpleImageLoadingListener(){
32 
33             @Override
34             public void onLoadingComplete(String imageUri, View view,
35                     Bitmap loadedImage) {
36                 super.onLoadingComplete(imageUri, view, loadedImage);
37                 mImageView.setImageBitmap(loadedImage);
38             }
39 
40         });

如果我們要指定圖片的大小該怎么辦呢,這也好辦,初始化一個ImageSize對象,指定圖片的寬和高,代碼如下

 1 final ImageView mImageView = (ImageView) findViewById(R.id.image);
 2         String imageUrl = "https://lh6.googleusercontent.com/-55osAWw3x0Q/URquUtcFr5I/AAAAAAAAAbs/rWlj1RUKrYI/s1024/A%252520Photographer.jpg";
 3 
 4         ImageSize mImageSize = new ImageSize(100, 100);
 5 
 6         ImageLoader.getInstance().loadImage(imageUrl, mImageSize, new SimpleImageLoadingListener(){
 7 
 8             @Override
 9             public void onLoadingComplete(String imageUri, View view,
10                     Bitmap loadedImage) {
11                 super.onLoadingComplete(imageUri, view, loadedImage);
12                 mImageView.setImageBitmap(loadedImage);
13             }
14 
15         });

上面只是很簡單的使用ImageLoader來加載網絡圖片,在實際的開發中,我們並不會這么使用,那我們平常會怎么使用呢?我們會用到 DisplayImageOptions,他可以配置一些圖片顯示的選項,比如圖片在加載中ImageView顯示的圖片,是否需要使用內存緩存,是否需 要使用文件緩存等等,可供我們選擇的配置如下

 1 DisplayImageOptions options = new DisplayImageOptions.Builder()
 2                 .showImageOnLoading(R.drawable.ic_stub) // 設置圖片下載期間顯示的圖片
 3                 .showImageForEmptyUri(R.drawable.ic_empty) // 設置圖片Uri為空或是錯誤的時候顯示的圖片
 4                 .showImageOnFail(R.drawable.ic_error) // 設置圖片加載或解碼過程中發生錯誤顯示的圖片
 5                 .resetViewBeforeLoading(false)  // default 設置圖片在加載前是否重置、復位
 6                 .delayBeforeLoading(1000)  // 下載前的延遲時間
 7                 .cacheInMemory(false) // default  設置下載的圖片是否緩存在內存中
 8                 .cacheOnDisk(false) // default  設置下載的圖片是否緩存在SD卡中
 9                 .preProcessor(...)
10                 .postProcessor(...)
11                 .extraForDownloader(...)
12                 .considerExifParams(false) // default
13                 .imageScaleType(ImageScaleType.IN_SAMPLE_POWER_OF_2) // default 設置圖片以如何的編碼方式顯示
14                 .bitmapConfig(Bitmap.Config.ARGB_8888) // default 設置圖片的解碼類型
15                 .decodingOptions(...)  // 圖片的解碼設置
16                 .displayer(new SimpleBitmapDisplayer()) // default  還可以設置圓角圖片new RoundedBitmapDisplayer(20)
17                 .handler(new Handler()) // default
18                 .build();
19 //
20 .imageScaleType(ImageScaleType imageScaleType)  //設置圖片的縮放方式
21     縮放類型mageScaleType:
22         EXACTLY :圖像將完全按比例縮小的目標大小
23         EXACTLY_STRETCHED:圖片會縮放到目標大小完全
24         IN_SAMPLE_INT:圖像將被二次采樣的整數倍
25         IN_SAMPLE_POWER_OF_2:圖片將降低2倍,直到下一減少步驟,使圖像更小的目標大小   
26         NONE:圖片不會調整
27     2).displayer(BitmapDisplayer displayer)  //設置圖片的顯示方式
28     顯示方式displayer:
29         RoundedBitmapDisplayer(int roundPixels)設置圓角圖片
30         FakeBitmapDisplayer()這個類什么都沒做
31         FadeInBitmapDisplayer(int durationMillis)設置圖片漸顯的時間
32         SimpleBitmapDisplayer()正常顯示一張圖片
33 //參數補充
34 .considerExifParams(true)  //是否考慮JPEG圖像EXIF參數(旋轉,翻轉)
35 .displayer(new FadeInBitmapDisplayer(100))// 圖片加載好后漸入的動畫時間
36 我們將上面的代碼稍微修改下
37 final ImageView mImageView = (ImageView) findViewById(R.id.image);
38         String imageUrl = "https://lh6.googleusercontent.com/-55osAWw3x0Q/URquUtcFr5I/AAAAAAAAAbs/rWlj1RUKrYI/s1024/A%252520Photographer.jpg";
39         ImageSize mImageSize = new ImageSize(100, 100);
40 
41         //顯示圖片的配置
42         DisplayImageOptions options = new DisplayImageOptions.Builder()
43                 .cacheInMemory(true)
44                 .cacheOnDisk(true)
45                 .bitmapConfig(Bitmap.Config.RGB_565)
46                 .build();
47 
48         ImageLoader.getInstance().loadImage(imageUrl, mImageSize, options, new SimpleImageLoadingListener(){
49 
50             @Override
51             public void onLoadingComplete(String imageUri, View view,
52                     Bitmap loadedImage) {
53                 super.onLoadingComplete(imageUri, view, loadedImage);
54                 mImageView.setImageBitmap(loadedImage);
55             }
56 
57         });
我們使用了DisplayImageOptions來配置顯示圖片的一些選項,這里我添加了將圖片緩存到內存中已經緩存圖片到文件系統中,這樣我們就不用 擔心每次都從網絡中去加載圖片了,是不是很方便呢,但是DisplayImageOptions選項中有些選項對於loadImage()方法是無效的, 比如showImageOnLoading, showImageForEmptyUri等,
 
displayImage()加載圖片
接下來我們就來看看網絡圖片加載的另一個方法displayImage(),代碼如下
 1 final ImageView mImageView = (ImageView) findViewById(R.id.image);
 2         String imageUrl = "https://lh6.googleusercontent.com/-55osAWw3x0Q/URquUtcFr5I/AAAAAAAAAbs/rWlj1RUKrYI/s1024/A%252520Photographer.jpg";
 3 
 4         //顯示圖片的配置
 5         DisplayImageOptions options = new DisplayImageOptions.Builder()
 6                 .showImageOnLoading(R.drawable.ic_stub)
 7                 .showImageOnFail(R.drawable.ic_error)
 8                 .cacheInMemory(true)
 9                 .cacheOnDisk(true)
10                 .bitmapConfig(Bitmap.Config.RGB_565)
11                 .build();
12 
13         ImageLoader.getInstance().displayImage(imageUrl, mImageView, options);

從上面的代碼中,我們可以看出,使用displayImage()比使用loadImage()方便很多,也不需要添加 ImageLoadingListener接口,我們也不需要手動設置ImageView顯示Bitmap對象,直接將ImageView作為參數傳遞到 displayImage()中就行了,圖片顯示的配置選項中,我們添加了一個圖片加載中ImageVIew上面顯示的圖片,以及圖片加載出現錯誤顯示的 圖片,效果如下,剛開始顯示ic_stub圖片,如果圖片加載成功顯示圖片,加載產生錯誤顯示ic_error

這個方法使用起來比較方便,而且使用displayImage()方法 他會根據控件的大小和imageScaleType來自動裁剪圖片,我們修改下MyApplication,開啟Log打印

 1 public class MyApplication extends Application {
 2 
 3     @Override
 4     public void onCreate() {
 5         super.onCreate();
 6 
 7         //創建默認的ImageLoader配置參數
 8         ImageLoaderConfiguration configuration = new ImageLoaderConfiguration.Builder(this)
 9         .writeDebugLogs() //打印log信息
10         .build();
11 
12 
13         //Initialize ImageLoader with configuration.
14         ImageLoader.getInstance().init(configuration);
15     }
16 
17 }

我們來看下圖片加載的Log信息

第一條信息中,告訴我們開始加載圖片,打印出圖片的url以及圖片的最大寬度和高度,圖片的寬高默認是設備的寬高,當然如果我們很清楚圖片的大小, 我們也可以去設置這個大小,在ImageLoaderConfiguration的選項中memoryCacheExtraOptions(int maxImageWidthForMemoryCache, int maxImageHeightForMemoryCache)

第二條信息顯示我們加載的圖片來源於網絡

第三條信息顯示圖片的原始大小為1024 x 682 經過裁剪變成了512 x 341 

第四條顯示圖片加入到了內存緩存中,我這里沒有加入到sd卡中,所以沒有加入文件緩存的Log

 

 
我們在加載網絡圖片的時候,經常有需要顯示圖片下載進度的需求,Universal-Image-Loader當然也提供這樣的功能,只需要在displayImage()方法中傳入ImageLoadingProgressListener接口就行了,代碼如下
1 imageLoader.displayImage(imageUrl, mImageView, options, new SimpleImageLoadingListener(), new ImageLoadingProgressListener() {
2 
3             @Override
4             public void onProgressUpdate(String imageUri, View view, int current,
5                     int total) {
6 
7             }
8         });
由於displayImage()方法中帶ImageLoadingProgressListener參數的方法都有帶 ImageLoadingListener參數,所以我這里直接new 一個SimpleImageLoadingListener,然后我們就可以在回調方法onProgressUpdate()得到圖片的加載進度。
 
 
加載其他來源的圖片
使用Universal-Image-Loader框架不僅可以加載網絡圖片,還可以加載sd卡中的圖片,Content provider等,使用也很簡單,只是將圖片的url稍加的改變下就行了,下面是加載文件系統的圖片
 1 //顯示圖片的配置
 2         DisplayImageOptions options = new DisplayImageOptions.Builder()
 3                 .showImageOnLoading(R.drawable.ic_stub)
 4                 .showImageOnFail(R.drawable.ic_error)
 5                 .cacheInMemory(true)
 6                 .cacheOnDisk(true)
 7                 .bitmapConfig(Bitmap.Config.RGB_565)
 8                 .build();
 9 
10         final ImageView mImageView = (ImageView) findViewById(R.id.image);
11         String imagePath = "/mnt/sdcard/image.png";
12         String imageUrl = Scheme.FILE.wrap(imagePath);
13 
14 //        String imageUrl = "http://img.my.csdn.net/uploads/201309/01/1378037235_7476.jpg";
15 
16         imageLoader.displayImage(imageUrl, mImageView, options);

當然還有來源於Content provider,drawable,assets中,使用的時候也很簡單,我們只需要給每個圖片來源的地方加上Scheme包裹起來(Content provider除外),然后當做圖片的url傳遞到imageLoader中,Universal-Image-Loader框架會根據不同的 Scheme獲取到輸入流

1 //圖片來源於Content provider
2         String contentprividerUrl = "content://media/external/audio/albumart/13";
3 
4         //圖片來源於assets
5         String assetsUrl = Scheme.ASSETS.wrap("image.png");
6 
7         //圖片來源於
8         String drawableUrl = Scheme.DRAWABLE.wrap("R.drawable.image");
GirdView,ListView加載圖片
相 信大部分人都是使用GridView,ListView來顯示大量的圖片,而當我們快速滑動GridView,ListView,我們希望能停止圖片的加 載,而在GridView,ListView停止滑動的時候加載當前界面的圖片,這個框架當然也提供這個功能,使用起來也很簡單,它提供了 PauseOnScrollListener這個類來控制ListView,GridView滑動過程中停止去加載圖片,該類使用的是代理模式
1 listView.setOnScrollListener(new PauseOnScrollListener(imageLoader, pauseOnScroll, pauseOnFling));
2         gridView.setOnScrollListener(new PauseOnScrollListener(imageLoader, pauseOnScroll, pauseOnFling));
第一個參數就是我們的圖片加載對象ImageLoader, 第二個是控制是否在滑動過程中暫停加載圖片,如果需要暫停傳true就行了,第三個參數控制猛的滑動界面的時候圖片是否加載
OutOfMemoryError
雖 然這個框架有很好的緩存機制,有效的避免了OOM的產生,一般的情況下產生OOM的概率比較小,但是並不能保證OutOfMemoryError永遠不發 生,這個框架對於OutOfMemoryError做了簡單的catch,保證我們的程序遇到OOM而不被crash掉,但是如果我們使用該框架經常發生 OOM,我們應該怎么去改善呢?
  • 減少線程池中線程的個數,在ImageLoaderConfiguration中的(.threadPoolSize)中配置,推薦配置1-5
  • 在DisplayImageOptions選項中配置bitmapConfig為Bitmap.Config.RGB_565,因為默認是ARGB_8888, 使用RGB_565會比使用ARGB_8888少消耗2倍的內存
  • 在ImageLoaderConfiguration中配置圖片的內存緩存為memoryCache(new WeakMemoryCache()) 或者不使用內存緩存
  • 在DisplayImageOptions選項中設置.imageScaleType(ImageScaleType.IN_SAMPLE_INT)或者imageScaleType(ImageScaleType.EXACTLY)
 
通 過上面這些,相信大家對Universal-Image-Loader框架的使用已經非常的了解了,我們在使用該框架的時候盡量的使用 displayImage()方法去加載圖片,loadImage()是將圖片對象回調到ImageLoadingListener接口的 onLoadingComplete()方法中,需要我們手動去設置到ImageView上面,displayImage()方法中,對 ImageView對象使用的是Weak references,方便垃圾回收器回收ImageView對象,如果我們要加載固定大小的圖片的時候,使用loadImage()方法需要傳遞一個 ImageSize對象,而displayImage()方法會根據ImageView對象的測量值,或者android:layout_width and android:layout_height設定的值,或者android:maxWidth and/or android:maxHeight設定的值來裁剪圖片


免責聲明!

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



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