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 原则,进行文件删除

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 qq糖粘在喉咙气管里怎么办 穿上旗袍后感觉后腰处不平整怎么办 机打票给客人给错联怎么办?急 ps修证件照感觉不太立体怎么办 手机百度上下载的文档打不开怎么办 5岁宝宝乘飞机没带证件怎么办 网上订飞机票忘记订儿童票了怎么办 两岁宝宝对牛奶鸡蛋过敏了怎么办 两岁宝宝坐不住好跑怎么办 宝宝两岁多了不愿意坐小马桶怎么办 坐火车小孩拉屎在被子上怎么办 川航飞机票名字错了一个字怎么办 胜战本领怎么看走向战场怎么办 数数字油画你的颜料干了怎么办? 数字油画涂颜料涂错了怎么办 绝地求生模拟器注册已达上限怎么办 孕妇把番茄和虾一起吃了怎么办 4岁宝贝吃了玩具小电池怎么办 微信使用零钱需完善实名信息怎么办 两岁宝宝刷牙不会吐水怎么办 孩子牙龈上长了小牙怎么办 供暖公司未供暖却收取供暖费怎么办 两岁宝宝认知和语言能力低怎么办 蜡笔同步被对方发现删掉的怎么办 微信时间和手机时间不同步怎么办 孩子们家乡爱画美丽的也自己怎么办 娃把豆豆弄进鼻孔了怎么办 20岁了不知道自己该干什么怎么办 遇到一个新手买家恶意拍下怎么办 淘宝卖螃蟹有什么要求美工怎么办 淘宝衣服吊牌剪了想退货怎么办修 用图片在淘宝搜衣服搜不到怎么办 汽车黑塑料水砂纸磨的不平怎么办 sat报名要你填10位电话怎么办 手绘板连接电脑绘画有点迟钝怎么办 走路不小心滑了一下特尴尬怎么办 小孩子头撞了头发长不出来怎么办 小孩子头磕破了不长头发怎么办 晚上洗了冷水头早上头痛怎么办 头发洗了一天就油了怎么办 米诺地尔搽剂喷了头皮油怎么办