Universal-Image-Loader源码收获
来源:互联网 发布:mac翻墙代理软件 编辑:程序博客网 时间:2024/06/06 18:00
不熟悉Universal-Image-Loader使用的同学,可参考:
“Universal-Image-Loader使用”
http://xiaxveliang.blog.163.com/blog/static/29708034201582853043103/
Universal-Image-Loader 如今使用广泛,最近也将公司项目中的图片下载引擎替换为了Universal-Image-Loader。
本着项目中不能加入不可控代码的原则,读了一遍Universal-Image-Loader 的源码,收获很大,想把自己学到的东西写下来,算是对自己有个交代,同时希望对大家有帮助。
通过源码,主要学习到了以下几点:
+ 1、两个线程池分别处理“sdcard已缓存的图片的获取”和“网络图片下载”任务。
好处很明显:防止出现“网络下载”占用线程资源,使得sdcard中的图片不能快速显示问题。
+ 2、采用“建造者”设计模式,方便程序扩展
Universal-Image-Loader 在初始化ImageLoader时,使用的内存缓存策略、sdcard缓存策略都是可选的,而且对这些类进行了抽象,可根据需要很方便的进行策略扩展。
+ 3、图片下载时,同样采用建造者模式,从而使圆角策略、圆形策略等可选可控可扩展。
+ 4、内存缓存LruMemoryCache
Sdcard卡缓存LruDiskCache
源码介绍:
一、两个线程池,一个处理网络图片下载,一个处理sdcard图片展示
ImageLoader类中,displayImage方法源码如下
public void displayImage(String uri, ImageAware imageAware, DisplayImageOptions options, ImageSize targetSize, ImageLoadingListener listener, ImageLoadingProgressListener progressListener) { ...... if (bmp != null && !bmp.isRecycled()) { ...... } else { ...... if (options.isSyncLoading()) { displayTask.run(); } else { engine.submit(displayTask); } } }
submit,是把任务提交到线程池,我们下面跟踪 submit 方法
ImageLoaderEngine类中,submit方法源码如下
/** * Submits task to execution pool */void submit(final LoadAndDisplayImageTask task) { taskDistributor.execute(new Runnable() { @Override public void run() { File image = configuration.diskCache.get(task.getLoadingUri()); boolean isImageCachedOnDisk = image != null && image.exists(); initExecutorsIfNeed(); if (isImageCachedOnDisk) { taskExecutorForCachedImages.execute(task); } else { taskExecutor.execute(task); } } });}
由源码可看出 taskExecutorForCachedImages 和 taskExecutor 分别为两个线程池。taskExecutor 处理网络下载任务
二、初始化时,采用建造者模式
public static void initUniversalImageLoader(Context context) { ImageLoaderConfiguration config; try { config = new ImageLoaderConfiguration.Builder(context) // 三线程 .threadPoolSize(3) // 任务队列,后进先出 .tasksProcessingOrder(QueueProcessingType.LIFO) // 图片大小限制 .memoryCacheExtraOptions(720, 1280) // 内存缓存的大小为30M .memoryCacheSize(30 * 1024 * 1024) // 采用lrumemory做内存缓存 .memoryCache(new LruMemoryCache(30 * 1024 * 1024) ) // sdcard缓存大小为300M,采用lru的方式进行缓存 .diskCache( new LruDiskCache( StorageUtils.getOwnCacheDirectory( context, "imageloader/pic"), new Md5FileNameGenerator(), 300 * 1024 * 1024) ) // sdcard文件名md5加密 .diskCacheFileNameGenerator(new Md5FileNameGenerator() ) // 开启log .writeDebugLogs() // .build(); ImageLoader.getInstance().init(config); } catch (IOException e) { e.printStackTrace(); }}
三、初始化时,采用建造者模式
DisplayImageOptions options = new DisplayImageOptions.Builder() // loading时的显示图片 .showImageOnLoading(R.drawable.ic_launcher) // 空url时的显示图片 .showImageForEmptyUri(R.drawable.ic_launcher) // 下载失败时的显示图片 .showImageOnFail(R.drawable.ic_launcher) // 缓存到内存 .cacheInMemory(true) // 缓存到sdcard .cacheOnDisk(true) // .considerExifParams(true) // View被重设 .resetViewBeforeLoading(true) // 显示图片为RGB565 .bitmapConfig(Bitmap.Config.RGB_565) // 圆角图 .displayer(new RoundedBitmapDisplayer(20)).build();ImageLoader.getInstance().displayImage("http://photocdn.sohu.com/20120530/Img344407929.jpg",imageView, options);
四、LruMemoryCache 内存缓存
用LinkedHashMap作内存缓存,限定一个最大内存,把最早使用的图片删除
LinkedHashMap<String, Bitmap> map = new LinkedHashMap<String, Bitmap>(0, 0.75f, true);
- WeakMemoryCache(这个类缓存bitmap的总大小没有限制,唯一不足的地方就是不稳定,缓存的图片容易被回收掉)
- LruMemoryCache(这个类就是这个开源框架默认的内存缓存类,缓存的是bitmap的强引用,下面我会从源码上面分析这个类)
- UsingFreqLimitedMemoryCache(如果缓存的图片总量超过限定值,先删除使用频率最小的bitmap)
- LRULimitedMemoryCache(这个也是使用的lru算法,和LruMemoryCache不同的是,他缓存的是bitmap的弱引用)
- FIFOLimitedMemoryCache(先进先出的缓存策略,当超过设定值,先删除最先加入缓存的bitmap)
- LargestLimitedMemoryCache(当超过缓存限定值,先删除最大的bitmap对象)
- LimitedAgeMemoryCache(当 bitmap加入缓存中的时间超过我们设定的值,将其删除)
Ps:这里有一个缓存是没有作用的LimitedAgeMemoryCache,这个缓存是每次从中get图片时,才会进行图片内存存活时间的判断,如果不get,岂不是永远在内存中了…
LruDiskCache Scard缓存
在图片缓存目录下,生成一个journal文件,文件中记录了文件的下载记录,读取记录,删除记录,文件大小等
文件内容如下:
//文件头libcore.io.DiskLruCache111// 存储记录DIRTY hzv6th5seqbt8mnsyuv043o6// 存储完成记录,文件大小记录CLEAN hzv6th5seqbt8mnsyuv043o6 24358// 读取记录READ hzv6th5seqbt8mnsyuv043o6// 文件移除记录REMOVE hzv6th5seqbt8mnsyuv043o6
每次进行文件的保存时,都会计算总文件大小是否超出了设定的大小,超过则根据 lru 原则,进行文件删除
- Universal-Image-Loader源码收获
- Android分析Universal-Image-Loader源码解析收获
- Universal-Image-Loader源码
- 源码解析 Universal Image Loader
- Universal Image Loader源码分析
- Universal-Image-Loader源码解析
- universal-image-loader源码解析
- universal-image-loader源码解析
- Android Universal Image Loader 源码分析
- Android Universal Image Loader 源码分析
- Android Universal Image Loader 源码分析
- Android Universal Image Loader 源码分析
- Android Universal Image Loader 源码分析
- Android Universal Image Loader 源码分析
- Android Universal Image Loader 源码分析
- Android Universal Image Loader 源码分析
- Android Universal Image Loader 源码分析
- Android Universal Image Loader 源码分析
- 解决用C#操作mysql数据库出错无法回滚的问题
- UVALive3520 UVa1590 POJ2799 IP Networks【进制+位运算】
- 什么是4:4:4、4:2:2、4:2:0?了解图像压缩取样的方式
- 两种创建线程的方式/线程的生命周期及各自使用同步锁时的区别
- 如何用Python写一个安卓APP
- Universal-Image-Loader源码收获
- Unsupported major.minor version 52.0异常
- .NET Reflector Visual Studio Extension
- hdu 3401 单调队列优化dp
- target-action
- android中RecyclerView的简单使用(二)——分割线
- Yii学习笔记1-介绍和详细运行过程
- Caffe在Windows上的搭建
- 使用比较器对Treemap按照key进行排序