(三)Doodle - 精简的图片加载框架 - 用法篇

本篇本系列的最后一篇,概述和原理见另外两篇文章:
(一)Doodle - 精简的图片加载框架 - 概述篇
(二)Doodle - 精简的图片加载框架 - 原理篇

一、下载

implementation 'io.github.billywei01:doodle:2.1.0'

二、Doodle (框架入口)

方法 描述
Config config() 返回全局配置。
Request load(String) 根据路径返回Request。
Request load(File) 根据文件返回Request。
Request load(int) 根据资源id返回Request。
Request load(Uri) 根据Uri返回Request。
File downloadOnly(String) 下载文件(不解码器)。注意不要在主线程调用此方法。
File getCacheFile(String) 获取缓存好的文件,没有则返回null。
void cacheBitmap(String,Bitmap,Boolean) 保存bitmap到缓存。
Bitmap getCacheBitmap(String): Bitmap? 从缓存中取bitmap, 无则返回null。
void pauseRequests() 暂停请求。
void resumeRequests() 恢复请求。
void notifyPause(Object) 发送pause事件。
void notifyResume(Object) 发送resume事件。
void notifyDestroy(Object) 发送destroy事件。
void trimMemory(int) 缩减内存缓存。
void clearMemory() 清除LruCache中的所有bitmap。

三、Config (全局配置)

全局配置的设置和Request类似,都是链式调用。

Doodle.config()
    .setLogger(Logger)
    .setExecutor(IOExecutor)
    .setHttpSourceFetcher(OkHttpSourceFetcher)
    .addAnimatedDecoders(GifDecoder)

全局配置中的各个选项都是可选的(可以不设置)。

方法 描述
setExecutor(Executor executor) 设置Executor。
APP中如果每个组件都创建自己的线程池并且保持核心线程不销毁,那整个APP的存活线程就很多了,容易导致OOM。
故此,编写框架的时候,最好留一个接口给调用者传入Executor, 这样APP可以统一管理线程,框架可以复用APP的线程池。
当然,Doodle内部会套队列来控制任务的并发量,具体做法原理篇有讲述。
setLogger(DLogger logger) 设置Logger。通过Log可以观察一些运行情况,输出错误日志等。
setCachePath(String) 设置结果缓存的存储路径。如果不设定,会默认在内部目录的cache目录下创建子目录。
setResultMaxCount(int) 设置果缓存最大数量,默认8192。
setResultCapacity(long) 设置结果缓存的容量,默认128M。
setSourceMaxCount(int) 设置原图缓存最大数量,默认4096。
setSourceCapacity(long) 设置原图缓存容量,默认256M。
setMemoryCacheCapacity(long) 设置内存缓存的容量,默认为maxMemory的1/6。
setCompressFormat(Bitmap.CompressFormat) 设置结果缓存的压缩格式。
如果不设定默认压缩格式,Doodle会根据解码格式(RGB_8888/RGB_565),文件类型,以及系统版本决定用哪一种压缩格式。
setHttpSourceFetcher(HttpSourceFetcher) Doodle内置了下载http文件的代码,用SDK自带的HttpURLConnection实现。
如果需要用自己的下载方法,实现HttpSourceFetcher并调此方法注入即可。
addDataParser(DataParser) 添加DataParser,用于自定义数据获取。
addAnimatedDecoders(AnimatedDecoder) 添加自定义AnimatedDecoder。
addBitmapDecoders(BitmapDecoder) 添加自定义BitmapDecoder。

全局配置中的HttpSourceFetcher和自定义解码,这里展开讲一下:

  • HttpSourceFetcher
    HttpSourceFetcher的定义很简单,传入url, 返回InputStream,如果请求失败,抛IOException。
public interface HttpSourceFetcher {
    InputStream getInputStream(String url) throws IOException;
}

需要指出的是,Doodle自己实现了磁盘缓存(包括网络文件缓存),如果使用OkHttp实现下载HttpSourceFetcher,
建议在请求的地方调用:

cacheControl(CacheControl.Builder().noStore().noCache().build())

以免缓存两份原文件。

  • 自定义解码
    Doodle提供了两个自定义解码接口:
public Config addAnimatedDecoders(AnimatedDecoder decoder)
public Config addBitmapDecoders(BitmapDecoder decoder)

接口比较简单,传入解码信息(包括数据源信息以及目标解码参数,具体可参考源码),返回结果。
例如,AnimatedDecoder定义如下:

public interface AnimatedDecoder {
    Object decode(DecodingInfo info);
}

如果需要支持解码GIF, 可以引入android-gif-drawable,实现DrawableDecoder接口。

import pl.droidsonroids.gif.GifDrawable

object GifDecoder : DrawableDecoder {
    override fun decode(info: DecodingInfo): Any? {
        if (info.mediaType != MediaType.GIF) {
            return null
        }
        val gifDrawable = GifDrawable(info.data)
        // 如果GIF文件只有一帧,可以返回Bitmap, 那样下次加载就可以直接读缓存了。
        if (gifDrawable.numberOfFrames == 1) {
            return gifDrawable.currentFrame
        }
        return gifDrawable
    }
}

然后在APP初始化时注册:

fun initApplication(context: Application) {
      Doodle.config().addDrawableDecoders(GifDecoder)
}

注册了Gif解码器后,常规调用即可:如果图片源是GIF动图,会解码得到GifDrawable。

Doodle.load(path).into(imageView)

当然也可以指定不需要显示动图, 调用asBitmap方法即可。

四、Request (加载请求)

  1. 加载图片到View (ImageView或者自定义View)
Doodle.load(path).into(imageView)
  1. 通过接口回调result
Doodle.load(path).into(result -> {
    if (result instanceof Bitmap) {
        // handle bitmap
    } else if (result instanceof Drawable) {
        // handle drawable
    } else { 
        // handle othe type (include null)
    }
});
  1. 直接获取bitmap
Bitmap bitmap = Doodle.load(path).get()
  1. 预加载:
Doodle.load(path).preload()

Doodle加载图片,从load()方法开始,到into(), get() 或者 preload()方法结束。
在into()/get()/preload()之前,可以添加更多的参数。

方法 描述
sourceKey(String) 设置数据源的key。
path默认情况下作为CacheKey的一部分,有时候path有动态的参数,使得path频繁变化,从而无法缓存。
此时可以取不变的部设置为sourceKey,替换path作为CacheKey的一部分。
override(int, int) 指定目标尺寸。
scaleType(ImageView.ScaleType) 指定缩放类型。
如果未设定,且target为ImageView,则会自动从ImageView获取。
clipType(ClipType) ClipType 是自定义缩放类型枚举,大部分和ScaleType重叠,有少量增删。
enableUpscale() 默认情况下,解码图片文件基于降采样的方式。
例如:
目标宽高是200x200,目标scaleType='centerCrop'。
1、文件分辨率是400x400,最终会解码出200x200的bitmap;
2、文件分辨率是100x100,最终会解码出100x100的bitmap。
第2种情况,由于源文件本身的分辨率只有100x100, 当ImageView的scaleType是centerCrop时,正常解码100x100和上采样成200x200的显示结果是一样的,后者并不会比前者清晰。
但有的情况就是要不管源文件分辨率,要求最终解码出的bitmap是目标宽高,这时候可以调用此方法。
memoryCacheStrategy(MemoryCacheStrategy) 设置内存缓存策略,默认LRU策略。
diskCacheStrategy(DiskCacheStrategy) 设置磁盘缓存策略,默认ALL。
noCache() 不做任何缓存,包括磁盘缓存和内存缓存。
onlyIfCached(boolean) 指定网络请求是否只从缓存读取(原图缓存)。
decodeFormat(DecodeFormat) 设置解码格式,默认ARGB_8888。
transform(Transformation) 设置解码后的图片变换(圆形剪裁,圆角,灰度,模糊等),可以连续调用(会按顺序执行)。
Doodle内置了圆形剪裁和圆角两种Transfromation。
keepOriginalDrawable() 默认情况下请求开始会先清空ImageView之前的Drawable, 调用此方法后会保留之前的Drawable,直到加载结束。
placeholder(int) 设置占位图,在结果加载完成之前会显示此drawable。
placeholder(Drawable) 同上。
error(int) 设置加载失败后的占位图。
error(Drawable) 同上。
animation(int) 设置加载成功后的过渡动画。
animation(Animation) 同上。
fadeIn(int) 加载成功后显示淡入动画。
crossFade(int) 这个动画效果是“原图”从透明度100到0, bitmap从0到100。
当设置placeholder时,placeholder为“原图”。
如果没有设置placeholder, 效果和fadeIn差不多。
需要注意的是,这个动画在原图和bitmap宽高不相等时,动画结束时图片会变形。
因此,慎用crossFade。
alwaysAnimation(Boolean) 默认情况下仅在图片是从磁盘或者网络加载出来时才做动画,可通过此方法设置总是做动画。
asBitmap() 当设置了GIF Decoder时,默认情况下只要图片是GIF图片,则用GIF Decoder解码。
调用此方法后,不走GIF解码器,直接用BitmapFactory解码,并返回bitmap。
observeHost(Object) 传入宿主(Activity/Fragment/View), 以观察其生命周期。
addOption(String, String) options目前有两个作用:
1. 传递参数给自定义Decoder;
2. 参与计算CacheKey, 以区分不同请求。
setBitmapDecoder(BitmapDecoder) 添加针对单个请求的BitmapDecoder。
此Decoder仅作用于当前Request, 并且会优先于其他自定义Decoder。
enableThumbnailDecoder() 这个选项是用于加速相册缩略图显示的,只对相册媒体(路径开头为"content://media/external/")有效。
相册中的媒体文件通常伴有生成好的缩略图文件,读取缩略图文件要比读取原文件要快很多。
缩率图文件分辨率较低,用于自定义相册的列表显示足够了。
开启此选项,会优先尝试读取缩略图,如果读取不到则访问原文件。
此选项仅作用于当前Request。
listen(CompleteListener) 监听加载任务结束时有没有取到结果。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,125评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,293评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,054评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,077评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,096评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,062评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,988评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,817评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,266评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,486评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,646评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,375评论 5 342
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,974评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,621评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,796评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,642评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,538评论 2 352

推荐阅读更多精彩内容