android異步加載圖片類(續)-universal-image-loader詳解

之前寫過一篇android異步加載圖片類 ,後來接觸瞭一個開源項目universal-image-loader,聽說淘寶也是用這玩意

發現自己寫的那個異步加載類太簡單瞭,雖然功能是實現瞭,但是很多優化的問題都沒有解決

比如:

同一個ui加載同一張圖,會出現隻加載一張,其他的加載不瞭

加載多圖的時候會有oom等問題

現在來說說universal-image-loader

特點:

多線程的圖像加載
的可能性的寬調諧對ImageLoader的配置(線程池的大小,HTTP選項,內存和光盤高速緩存,顯示圖像,以及其他)
的圖像的可能性中的緩存存儲器和/或設備的文件器系統(或SD卡)
可以“聽”加載過程中
可自定義每個顯示的圖像調用分隔的選項
Widget支持
Android 1.5以上支持

使用方法:(我自己封裝瞭一個類ImgConfig使用,方便一些)

隻需兩步即可加載網絡圖片:

一、初始化

ImgConfig.initImageLoader();

二、

ImgConfig.showUserSImg(imgUrl, imageview); //圖片的url,要顯示的view

以下是我自己寫的ImgConfig,僅供參考:

public class ImgConfig extends ImageLoader {
	private static DisplayImageOptions options_corner;
	private static DisplayImageOptions options_square;
	private static AnimateFirstDisplayListener animateFirstDisplayListener = new AnimateFirstDisplayListener();

	/**
	 * @param url   服務器的文件名
	 * @param imageView
	 *            顯示方形圖片 S for Square
	 */
	public static void showUserSImg(String url, ImageView imageView) {
		ImageLoader.getInstance().displayImage(url,
				imageView, options_square, animateFirstDisplayListener);
	}

	/**
	 * @param url   服務器的文件名
	 * @param imageView
	 *            圓角 C for Corner
	 */
	public static void showUserCImg(String url, ImageView imageView) {
		ImageLoader.getInstance().displayImage(url,
				imageView, options_corner, animateFirstDisplayListener);
	}
	
	/**
	 * 初始化圖片讀取方式
	 */
	public static void initImageLoader() {

		DisplayImageOptions options_corner = new DisplayImageOptions.Builder()
				.showImageOnLoading(ImgHandler.ToCircular(R.drawable.defult_head))
				// 加載中
				.showImageForEmptyUri(ImgHandler.ToCircular(R.drawable.defult_head))
				// 空uri
				.showImageOnFail(ImgHandler.ToCircular(R.drawable.defult_head))
				// 失敗時
				.cacheInMemory(true)
				// 設置下載的圖片是否緩存在內存中
				.cacheOnDisc(true)
				// 設置下載的圖片是否緩存在SD卡中
				.considerExifParams(true)
				.displayer(new RoundedBitmapDisplayer(10)) // 展現方式:圓角
				.resetViewBeforeLoading(true)
				.imageScaleType(ImageScaleType.EXACTLY)
				// new FadeInBitmapDisplayer(300) 漸現
				.build();


		options_square = new DisplayImageOptions.Builder()
		.showImageOnLoading(R.drawable.defult_head)
		.showImageForEmptyUri(R.drawable.defult_head)
		.showImageOnFail(R.drawable.defult_head)
		.cacheInMemory(true)
		.cacheOnDisc(true)
		.considerExifParams(true)
		.displayer(new FadeInBitmapDisplayer(100)) // 展現方式:漸現
		.resetViewBeforeLoading(true)
		.imageScaleType(ImageScaleType.EXACTLY)
		.build();
		
		// This configuration tuning is custom. You can tune every option, you
		// may tune some of them,
		// or you can create default configuration by
		// ImageLoaderConfiguration.createDefault(this);
		// method.
		ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(
				ContextUtil.getInstance())
				.threadPriority(Thread.NORM_PRIORITY)  //線程池的數量
				.denyCacheImageMultipleSizesInMemory() // 不同大小圖片隻有一個緩存,默認多個
				.tasksProcessingOrder(QueueProcessingType.LIFO)
				// 設置圖片下載和顯示的工作隊列排序
				.discCache(new LimitedAgeDiscCache(new File(Constant.SAVE_IMG_PATH),
								new Md5FileNameGenerator(), 7 * 24 * 60 * 60)) // 7天自動清除,按秒算
				// .writeDebugLogs() // Remove for release app
				.imageDownloader(     //或許你的服務器有特定的加載圖的方式,在這裡實現
						new BaseImageDownloader(ContextUtil.getInstance()) {
							@Override
							public InputStream getStream(String imageUri,
									Object extra) throws IOException {
								return super.getStream(imageUri, extra);
							}

							@Override
							protected InputStream getStreamFromNetwork(
									String imageUri, Object extra)
									throws IOException {
								HttpURLConnection conn = createConnection(
										imageUri, extra);

								int redirectCount = 0;
								while (conn.getResponseCode() / 100 == 3
										&& redirectCount < MAX_REDIRECT_COUNT) {
									conn = createConnection(
											conn.getHeaderField("Location"),
											extra);
									redirectCount++;
								}

								InputStream imageStream = null;
								try {
									imageStream = conn.getInputStream();
								} catch (IOException e) {
									// Read all data to allow reuse connection
									// (https://bit.ly/1ad35PY)
									IoUtils.readAndCloseStream(conn
											.getErrorStream());
								}
								return new ContentLengthInputStream(
										new BufferedInputStream(imageStream,
												BUFFER_SIZE), conn
												.getContentLength());
							}
						}).build();
		// Initialize ImageLoader with configuration.  初始化
		ImageLoader.getInstance().init(config);
	}
	
	/**
	 * @author Administrator 監聽讀取完圖片
	 */
	private static class AnimateFirstDisplayListener extends
			SimpleImageLoadingListener {
		// 放到內存
		static final List displayedImages = Collections
				.synchronizedList(new LinkedList());

		@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);
				}
			}
		}
	}

}

特別提示以下 .disCache() 和 .imageDownloader

因為我不想要自動幫我加密文件,所以我.disCache() 裡面的加密方法 new Md5FileNameGenerator()

換成瞭

new FileNameGenerator() {
									@Override
									public String generate(String imageUri) {
										return FileUtil.getFileName(imageUri);
									}
								}

服務器有自己的加載方式,我把加載.imageDownloader的加載圖片方法換瞭

new BaseImageDownloader(ContextUtil.getInstance()) {
							@Override
							public InputStream getStream(String imageUri,
									Object extra) throws IOException {
								return super.getStream(imageUri, extra);
							}

							@Override
							protected InputStream getStreamFromNetwork(
									String imageUri, Object extra)
									throws IOException {
								HttpURLConnection conn = createConnection(
										imageUri, extra);

								int redirectCount = 0;
								while (conn.getResponseCode() / 100 == 3
										&& redirectCount < MAX_REDIRECT_COUNT) {
									conn = createConnection(
											conn.getHeaderField("Location"),
											extra);
									redirectCount++;
								}

								InputStream imageStream = null;
								try {
									imageStream = conn.getInputStream();
								} catch (IOException e) {
									// Read all data to allow reuse connection
									// (https://bit.ly/1ad35PY)
									IoUtils.readAndCloseStream(conn
											.getErrorStream());
								}
								return new ContentLengthInputStream(
										new BufferedInputStream(imageStream,
												BUFFER_SIZE), conn
												.getContentLength());
							}
						}

總結: universal-image-loader 這個開源項目很好用,

研究瞭一下源碼,有很多啟發,擴展性很好,值得我們學習

官方提供的例子:
universal-image-loader例子

發佈留言