ImageLoader是一个图片加载开源框架,下面就简称为UIL。
一、UIL的使用
ImageView imageView = (ImageView) findViewById(R.id.imageview);
DisplayImageOptions options = new DisplayImageOptions.Builder()
.cacheInMemory(true)
.cacheOnDisc(true)
.bitmapConfig(Bitmap.Config.RGB_565)
.build();
ImageLoader.getInstance().displayImage("url", imageView, options);
二、源码分析
看一下displayImage方法内部是怎样实现的,
可以看到ImageLoader.java类的displayImage方法中将imageview转换成了ImageViewAware。ImageViewAware主要哦是将ImageView做了一个封装,将强引用改为弱引用,所以当内存不够时,可以更好的回收这些imageview对象。
接下来看displayImage方法的具体实现:
第236行代码checkConfiguration()的方法实现:
这个方法主要是检查ImageLoader的初始化,若初始化信息为null时就抛一个异常。
接下来看247到257行的代码:
这里主要是判断url为null时怎么处理,看一下ImageLoaderEngine类:
cacheKeysForImageAwares还是通过一个HashMap实现的,这也就是将所有的属性都放到一个HashMap中。
回到刚才的代码,248行主要是当url为null时,将图片的尺寸、id,加载到一个集合当中,加载完成后从内存中移除掉。
251行,将属性设置给imageAware也就是我们的imageView
255行,完成后通过listener回调告诉我们这次任务完成了。
再往下看,这里有一个targetSize
点进去看一下,
主要是将imageview的宽、高封装成imageSize对象,当宽为0的时候,就会使用手机屏幕的宽(高也一样)。例如listview在加载图片时,第一项宽度为0,使用的就是屏幕的宽度。
在获得targetSize之后,会进行memoryCache操作,就是从内存中获取图片,这里是get操作(267行),看一下具体实现,在LruMemoryCache.java中
这里面默认使用的是LRU算法。
回到代码,通过get操作得到一个缓存的bitmap对象。接着判断bmp是否为null,是否被回收,如果不为null并且也没回收,就从内存中加载。反之从网络加载。
297行,run方法开启了一个线程。看一下LoadAndDisplayImageTask类中的run具体实现,
123行,根据图片url获得一个重入锁,主要用于listview,item滚入滚进的情景
129行,让重入锁等待,等到图片加载完成,锁释放
134行,从memoryCache中获取bitmap对象,当内存中没有便去磁盘中获取,如果磁盘中没有便去网络上获取
136行,tryLoadBitmap方法,
回到刚才代码处,看175、176行,DisplayBitmapTask的实现也是一个runnable。
DisplayBitmapTask.java中run方法:
判断imageview是否被回收,是否被重用,要是被回收或者被重用了,就调用listener的onLoadingCancelled方法,取消显示。负责就用display方法显示,并通过listener完成回调。