UniversalImageLoader源码解读01-用来显示图片的ImageAware

    Android平台下有一个著名的图片加载框架叫UniversalImageLoader,这个框架经过几次重构才有今天,有良好的扩展性。如果你曾经在ListView中加载图片出现过图片错乱,如果你曾经因加载图片过多而遇到OOM,那么你应该考虑使用UniversalImageLoader了。


    UniversalImageLoader支持二级缓存,内存+磁盘缓存,图片一旦从网络下载后会保存在磁盘缓存里并缓存到内存,这样下次就不会去网络上重新下载,并且内存中如果存在就不会去磁盘上加载,在有限的内存设备上,这种方法增加了内存的换入换出操作,但是总的来说比烦人的OOM要好得多。


    本人使用的版本 Version name 1.9.4 Version code 39

    为了能够看懂UniversalImageLoader的源码,以下内容你必须知道怎么回事,否则读源码会有困难。本文假定读者有基本的Android控件编程能力。

    1) Java多线程的 Executor, 以及ExecutorService, WeakReference如何使用(网上自己去查)

    2) 如何使用 UniversalImageLoader(Sample code里有)


    解读源码是一件很痛苦的事,因为有时候我们明明知道整个项目是如何工作的,结构如何等等,但是真要是说明白却不知道从哪里下手,在此本人试图说清,欢迎拍砖

    下面从包的级别开始,从外层到最核心的代码

    com.nostra13.universalimageloader.core.imageaware 封装了图片组件,它将使用图片的控件抽象成 ImageAware,

ViewAware实现了ImageAware接口, ImageViewAware继承ViewAware, NonViewAware也实现了ImageAware接口  ViewAware的接口定义如下:


/* 理解UniversalImageLoader最好的方式就是先去搞清楚如何使用,然后去看每个包下面的接口,
   因为UIL充分利用了接口进行抽象,封装了变化,实现了很好的可扩展性。为了方便说明,这里假定是ImageView的一个抽象,定义非常简单*/
public interface ImageAware {

	int getWidth(); //获取ImageView的宽度

	int getHeight(); //获取ImageView的高度

	ViewScaleType getScaleType();//获取ImageView的缩放类型

	View getWrappedView();// 这个就是组件包装的View,通常是个ImageView,当然也可以是其他的View

	boolean isCollected();// 判断View是否被回收,后面会解释

	int getId();

	boolean setImageDrawable(Drawable drawable);// 给包装的View设置图片

	boolean setImageBitmap(Bitmap bitmap);} // 给包装的View设置图片



 /* 这个抽象类实现了大部分方法,而把设置图片的工作留给子类*/

public abstract class ViewAware implements ImageAware {

	public static final String WARN_CANT_SET_DRAWABLE = "Can't set a drawable into view. You should call ImageLoader on UI thread for it.";
	public static final String WARN_CANT_SET_BITMAP = "Can't set a bitmap into view. You should call ImageLoader on UI thread for it.";

	protected Reference<View> viewRef;//这就是为什么isCollected方法的由来
	protected boolean checkActualViewSize;

	public ViewAware(View view) {
		this(view, true);
	}

	public ViewAware(View view, boolean checkActualViewSize) {
		if (view == null) throw new IllegalArgumentException("view must not be null");

		this.viewRef = new WeakReference<View>(view);//采用弱引用包装,这样做会为Bitmap的缓存提供方便,如果被回收了,那么Bitmap或许没必要缓存了
		this.checkActualViewSize = checkActualViewSize;//尽量获取实际的View宽高,是尽量,如果获取不到,那就取布局参数的宽高
	}

	@Override
	public int getWidth() {
		View view = viewRef.get();
		if (view != null) {
			final ViewGroup.LayoutParams params = view.getLayoutParams();
			int width = 0;
			if (checkActualViewSize && params != null && params.width != ViewGroup.LayoutParams.WRAP_CONTENT) {
				width = view.getWidth(); // Get actual image width
			}
			if (width <= 0 && params != null) width = params.width; // Get layout width parameter
			return width;
		}
		return 0;
	}

	@Override
	public int getHeight() {
		View view = viewRef.get();
		if (view != null) {
			final ViewGroup.LayoutParams params = view.getLayoutParams();
			int height = 0;
			if (checkActualViewSize && params != null && params.height != ViewGroup.LayoutParams.WRAP_CONTENT) {
				height = view.getHeight(); // Get actual image height
			}
			if (height <= 0 && params != null) height = params.height; // Get layout height parameter
			return height;
		}
		return 0;
	}

	@Override
	public ViewScaleType getScaleType() {
		return ViewScaleType.CROP;
	}

	@Override
	public View getWrappedView() {
		return viewRef.get();// 可能为null
	}

	@Override
	public boolean isCollected() {
		return viewRef.get() == null;
	}

	@Override
	public int getId() {
		View view = viewRef.get();
		return view == null ? super.hashCode() : view.hashCode();
	}

	@Override
	public boolean setImageDrawable(Drawable drawable) {
		if (Looper.myLooper() == Looper.getMainLooper()) {
			View view = viewRef.get();
			if (view != null) {
				setImageDrawableInto(drawable, view);
				return true;
			}
		} else {
			L.w(WARN_CANT_SET_DRAWABLE);
		}
		return false;
	}

	@Override
	public boolean setImageBitmap(Bitmap bitmap) {
		if (Looper.myLooper() == Looper.getMainLooper()) {
			View view = viewRef.get();
			if (view != null) {
				setImageBitmapInto(bitmap, view);
				return true;
			}
		} else {
			L.w(WARN_CANT_SET_BITMAP);
		}
		return false;
	}

	protected abstract void setImageDrawableInto(Drawable drawable, View view);
	protected abstract void setImageBitmapInto(Bitmap bitmap, View view);
}



你可能感兴趣的:(ImageLoader源码解读)