1. 程式人生 > >Universal-Image-Loader(android圖片快取)

Universal-Image-Loader(android圖片快取)

詳細資料整理請加群284568173自行下載pdf

專案介紹:

Android上最讓人頭疼的莫過於從網路獲取圖片、顯示、回收,任何一個環節有問題都可能直接OOM,這個專案或許能幫到你。Universal Image Loader for Android的目的是為了實現非同步的網路圖片載入、快取及顯示,支援多執行緒非同步載入。它最初來源於Fedor Vlasov的專案,且自此之後,經過大規模的重構和改進。

特性列舉:

  1. 多執行緒下載圖片,圖片可以來源於網路,檔案系統,專案資料夾assets中以及drawable中等
  2. 支援隨意的配置ImageLoader,例如執行緒池,圖片下載器,記憶體快取策略,硬碟快取策略,圖片顯示選項以及其他的一些配置
  3. 支援圖片的記憶體快取,檔案系統快取或者SD卡快取
  4. 支援圖片下載過程的監聽
  5. 根據控制元件(ImageView)的大小對Bitmap進行裁剪,減少Bitmap佔用過多的記憶體
  6. 較好的控制圖片的載入過程,例如暫停圖片載入,重新開始載入圖片,一般使用在ListView,GridView中,滑動過程中暫停載入圖片,停止滑動的時候去載入圖片
  7. 提供在較慢的網路下對圖片進行載入

使用過程:

建立預設的ImageLoader,所有的操作都由ImageLoader控制。該類使用單例設計模式,所以如果要獲取該類的實力,需要呼叫getInstance()方法。在使用ImageLoader顯示圖片之前,你首先要初始化它的配置,呼叫ImageLoaderConfiguration的init()方法,然後你就可以實現各種的顯示了。

        //建立預設的ImageLoader配置引數  
        ImageLoaderConfiguration configuration = ImageLoaderConfiguration  
                .createDefault(this);  
        //Initialize ImageLoader with configuration.  
        ImageLoader.getInstance().init(configuration); 


自定義配置imageloader, 就像你已經知道的,首先,你需要使用ImageLoaderConfiguration物件來初始化ImageLoader。由於ImageLoader是單例,所以在程式開始的時候只需要初始化一次就好了。建議你在Activity的onCreate()方法中初始化。如果一個ImageLoader已經初始化過,再次初始化不會有任何效果。下面我們通過ImageLoaderConfiguration.Builder建立一個設定

File cacheDir =StorageUtils.getOwnCacheDirectory(this, "imageloader/Cache");
ImageLoaderConfigurationconfig = new ImageLoaderConfiguration 
          .Builder(this) 
          .memoryCacheExtraOptions(480, 800) // maxwidth, max height,即儲存的每個快取檔案的最大長寬 
          .threadPoolSize(3)//執行緒池內載入的數量 
          .threadPriority(Thread.NORM_PRIORITY -2) 
          .denyCacheImageMultipleSizesInMemory() 
           .memoryCache(new UsingFreqLimitedMemoryCache(2* 1024 * 1024)) // You can pass your own memory cache implementation/你可以通過自己的記憶體快取實現 
           .memoryCacheSize(2 * 1024 * 1024)   
          .discCacheSize(50 * 1024 * 1024)   
          .discCacheFileNameGenerator(newMd5FileNameGenerator())//將儲存的時候的URI名稱用MD5 加密 
           .tasksProcessingOrder(QueueProcessingType.LIFO) 
           .discCacheFileCount(100) //快取的檔案數量 
           .discCache(new UnlimitedDiscCache(cacheDir))//自定義快取路徑 
           .defaultDisplayImageOptions(DisplayImageOptions.createSimple()) 
           .imageDownloader(new BaseImageDownloader(this,5 * 1000, 30 * 1000)) // connectTimeout (5 s), readTimeout (30 s)超時時間 
           .writeDebugLogs() // Remove for releaseapp 
          .build();//開始構建 
ImageLoader.getInstance().init(config);


得到imageLoader

ImageLoader imageLoader imageLoader = ImageLoader.getInstance();

使用過程:

(1)影象操作是否參與快取以及影象效果的配置操作

DisplayImageOptions options = new DisplayImageOptions.Builder()
          .showImageOnLoading(R.drawable.ic_stub)            //載入圖片時的圖片
          .showImageForEmptyUri(R.drawable.ic_empty)         //沒有圖片資源時的預設圖片
          .showImageOnFail(R.drawable.ic_error)              //載入失敗時的圖片
          .cacheInMemory(true)                               //啟用記憶體快取
          .cacheOnDisk(true)                                 //啟用外存快取
          .considerExifParams(true)                          //啟用EXIF和JPEG影象格式
          .displayer(new RoundedBitmapDisplayer(20))         //設定顯示風格這裡是圓角矩形
          .build();


DisplayImageOptions以下是所有預設配置引數根據需求可以自定義配置

                   private int imageResOnLoading = 0;
                    private int imageResForEmptyUri = 0;
                    private int imageResOnFail = 0;
                    private Drawable imageOnLoading = null;
                    private Drawable imageForEmptyUri = null;
                    private Drawable imageOnFail = null;
                    private boolean resetViewBeforeLoading = false;
                    private boolean cacheInMemory = false;
                    private boolean cacheOnDisk = false;
                    private ImageScaleType imageScaleType = ImageScaleType.IN_SAMPLE_POWER_OF_2;
                    private Options decodingOptions = new Options();
                    private int delayBeforeLoading = 0;
                    private boolean considerExifParams = false;
                    private Object extraForDownloader = null;
                    private BitmapProcessor preProcessor = null;
                    private BitmapProcessor postProcessor = null;
                    private BitmapDisplayer displayer = DefaultConfigurationFactory.createBitmapDisplayer();
                    private Handler handler = null;
                    private boolean isSyncLoading = false;

(2)圖片載入監聽器在這裡吧可以設定載入時的動畫或者進度條之類的東西這裡

ImageLoadingListener animateFirstListener = new AnimateFirstDisplayListener();
private static class AnimateFirstDisplayListener extends SimpleImageLoadingListener {
        static final List<String> displayedImages = Collections.synchronizedList(new LinkedList<String>());
         @Override
         public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
              if (loadedImage != null) {
                  ImageView imageView = (ImageView) view;
                  boolean firstDisplay = !displayedImages.contains(imageUri);
                  if (firstDisplay) {
                       FadeInBitmapDisplayer.animate(imageView, 500);
                       displayedImages.add(imageUri);
                    }
              }
        }
}


(3)簡單設定就可以給ImageView新增圖片了

imageLoader.displayImage(imageUrl, imageview, options, animateFirstListener);

對於本地的圖片 ,在其絕對地址前面要加入"file://"。網路圖片就直接寫路徑了。

由於我的這個是最新的包,可能跟以前老的版本不同,看到有些網友說的是:

String imageUri = "http://site.com/image.png"; // 網路圖片
String imageUri = "file:///mnt/sdcard/image.png"; //SD卡圖片
String imageUri = "content://media/external/audio/albumart/13"; // 媒體資料夾
String imageUri = "assets://image.png"; // assets
String imageUri = "drawable://" + R.drawable.image; //  drawable檔案 

快取的清理:

       快取的清理可以按需求來定,可以再每個Activity的生命週期函式onDestroy中清理也可以單獨設定讓使用者自行清理。

          @Override
          public void onDestroy() {
                    super.onDestroy();
                    imageLoader.clearMemoryCache();
                    imageLoader.clearDiskCache();
          }


GirdView,ListView載入圖片:

相信大部分人都是使用GridView,ListView來顯示大量的圖片,而當我們快速滑動GridView,ListView,我們希望能停止圖片的載入,而在GridView,ListView停止滑動的時候載入當前介面的圖片,這個框架當然也提供這個功能,使用起來也很簡單,它提供了PauseOnScrollListener這個類來控制ListView,GridView滑動過程中停止去載入圖片,該類使用的是代理模式

listView.setOnScrollListener(new PauseOnScrollListener(imageLoader, pauseOnScroll, pauseOnFling));  
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(newWeakMemoryCache()) 或者不使用記憶體快取

在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設定的值來裁剪圖片