標籤:
原文http://write.blog.csdn.net/postedit?ref=toolbar
項目介紹:
Android上最讓人頭疼的莫過於從網路擷取圖片、顯示、回收,任何一個環節有問題都可能直接OOM,這個項目或許能幫到你。Universal Image Loader for Android的目的是為了實現非同步網狀圖片載入、緩衝及顯示,支援多線程非同步載入。它最初來源於Fedor Vlasov的項目,且自此之後,經過大規模的重構和改進。
特性列舉:
- 多線程下載圖片,圖片可以來源於網路,檔案系統,專案檔夾assets中以及drawable中等
- 支援隨意的配置ImageLoader,例如線程池,圖片下載器,記憶體緩衝策略,硬碟緩衝策略,圖片顯示選項以及其他的一些配置
- 支援圖片的記憶體緩衝,檔案系統快取或者SD卡緩衝
- 支援圖片下載過程的監聽
- 根據控制項(ImageView)的大小對Bitmap進行裁剪,減少Bitmap佔用過多的記憶體
- 較好的控製圖片的載入過程,例如暫停圖片載入,重新開始載入圖片,一般使用在ListView,GridView中,滑動過程中暫停載入圖片,停止滑動的時候去載入圖片
- 提供在較慢的網路下對圖片進行載入
使用過程:
建立預設的ImageLoader,所有的操作都由ImageLoader控制。該類使用單例設計模式,所以如果要擷取該類的實力,需要調用getInstance()方法。在使用ImageLoader顯示圖片之前,你首先要初始化它的配置,調用ImageLoaderConfiguration的init()方法,然後你就可以實現各種的顯示了。
1 //建立預設的ImageLoader配置參數 2 ImageLoaderConfiguration configuration = ImageLoaderConfiguration 3 .createDefault(this); 4 //Initialize ImageLoader with configuration. 5 ImageLoader.getInstance().init(configuration);
自訂配置imageloader, 就像你已經知道的,首先,你需要使用ImageLoaderConfiguration對象來初始化ImageLoader。由於ImageLoader是單例,所以在程式開始的時候只需要初始化一次就好了。建議你在Activity的onCreate()方法中初始化。如果一個ImageLoader已經初始化過,再次初始化不會有任何效果。下面我們通過ImageLoaderConfiguration.Builder建立一個設定
1 File cacheDir =StorageUtils.getOwnCacheDirectory(this, "imageloader/Cache"); 2 ImageLoaderConfigurationconfig = new ImageLoaderConfiguration 3 .Builder(this) 4 .memoryCacheExtraOptions(480, 800) // maxwidth, max height,即儲存的每個快取檔案的最大長寬 5 .threadPoolSize(3)//線程池內載入的數量 6 .threadPriority(Thread.NORM_PRIORITY -2) 7 .denyCacheImageMultipleSizesInMemory() 8 .memoryCache(new UsingFreqLimitedMemoryCache(2* 1024 * 1024)) // You can pass your own memory cache implementation/你可以通過自己的記憶體緩衝實現 9 .memoryCacheSize(2 * 1024 * 1024) 10 .discCacheSize(50 * 1024 * 1024) 11 .discCacheFileNameGenerator(newMd5FileNameGenerator())//將儲存的時候的URI名稱用MD5 加密 12 .tasksProcessingOrder(QueueProcessingType.LIFO) 13 .discCacheFileCount(100) //緩衝的檔案數量 14 .discCache(new UnlimitedDiscCache(cacheDir))//自訂緩衝路徑 15 .defaultDisplayImageOptions(DisplayImageOptions.createSimple()) 16 .imageDownloader(new BaseImageDownloader(this,5 * 1000, 30 * 1000)) // connectTimeout (5 s), readTimeout (30 s)逾時時間 17 .writeDebugLogs() // Remove for releaseapp 18 .build();//開始構建 19 ImageLoader.getInstance().init(config);
得到imageLoader
1 ImageLoader imageLoader imageLoader = ImageLoader.getInstance();
使用過程:
(1)映像操作是否參與緩衝以及映像效果的配置操作
1 DisplayImageOptions options = new DisplayImageOptions.Builder()2 .showImageOnLoading(R.drawable.ic_stub) //載入圖片時的圖片3 .showImageForEmptyUri(R.drawable.ic_empty) //沒有圖片資源時的預設圖片4 .showImageOnFail(R.drawable.ic_error) //載入失敗時的圖片5 .cacheInMemory(true) //啟用記憶體緩衝6 .cacheOnDisk(true) //啟用外存緩衝7 .considerExifParams(true) //啟用EXIF和JPEG映像格式8 .displayer(new RoundedBitmapDisplayer(20)) //設定顯示風格這裡是圓角矩形9 .build();
DisplayImageOptions以下是所有預設配置參數根據需求可以自訂配置
1 private int imageResOnLoading = 0; 2 private int imageResForEmptyUri = 0; 3 private int imageResOnFail = 0; 4 private Drawable imageOnLoading = null; 5 private Drawable imageForEmptyUri = null; 6 private Drawable imageOnFail = null; 7 private boolean resetViewBeforeLoading = false; 8 private boolean cacheInMemory = false; 9 private boolean cacheOnDisk = false;10 private ImageScaleType imageScaleType = ImageScaleType.IN_SAMPLE_POWER_OF_2;11 private Options decodingOptions = new Options();12 private int delayBeforeLoading = 0;13 private boolean considerExifParams = false;14 private Object extraForDownloader = null;15 private BitmapProcessor preProcessor = null;16 private BitmapProcessor postProcessor = null;17 private BitmapDisplayer displayer = DefaultConfigurationFactory.createBitmapDisplayer();18 private Handler handler = null;19 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添加圖片了
1 imageLoader.displayImage(imageUrl, imageview, options, animateFirstListener);
緩衝的清理:
緩衝的清理可以按需求來定,可以再每個Activity的生命週期函數onDestroy中清理也可以單獨設定讓使用者自行清理。
@Override public void onDestroy() { super.onDestroy(); imageLoader.clearMemoryCache(); imageLoader.clearDiskCache(); }
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(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設定的值來裁剪圖片
【轉】Universal-Image-Loader(android圖片緩衝)