android 图片加载库(5)- 图片加载库如何封装

前言


前面2篇文章分别学习了 Glide 和 Fresco ,如果说之前的 Glide 在内存上不如 Fresco 优秀的话,那么至少新版的 Glide V 4.X 版本在 API 21 之后的android 系统上和 Fresco 打成平手了,甚至比 Fresco 在 Heap 堆内存占用上还要优秀一些,当然优秀有限,这样因为 Fresco 可不会像 Glide 一样根据 view 的宽高压缩图片分辨率,当然 Fresco 我们可以在每次请求时根据 view 的宽高来计算图片的分辨率,然后 resize ,当时这种方法毕竟不如 Glide 原生实现的优秀。

图片加载库有不少,但是随着时间推移,相关项目有的稳步发展,有的趋于沉寂,综合性能,功能来说,现在给我们的选择其实只有2个 - Glide 和 Fresco:

  • Glide
    新版 Glide 在 5.0 之后的系统性能比 Fresco 稍好,但是功能没有 Fresco 强,包的体积小,只有900K 左右
  • Fresco
    Fresco 太过于重量了,最新版本的大小有 5M 左右,但是功能很多,5.0 之前的系统,Fresco 因为使用 Ashmeme 匿名共享内存的关系,性能那是杠杠的。

最大的困难


我们在封装自己的图片加载库功能模式时,最大的困难来源于 Fresco,对 Fresco 这货因为支持太多的功能了,所以是用的 view 是自己写的,不再是 imageview 了,是 SimpleDraweeView ,这货虽然继承自 imageview ,但是 imageview 的相关方法都被注为过时了,都不能用。控件的不统一,造成了我们 xml 书写的最大问题,到底用那个 view 啊,要是哪天 Fresco 过时了,再换一个库还来一个新的 view 怎么办啊,所以这个问题真是太坑了。

在介绍 Fresco 的章节中,提了一下 Fresco 的非侵入式设计,里面说了3种 Fresco 的兼容方式, 但是根据查阅资料和实际对比:

结论是我们要使用 Fresco 的化,SimpleDraweeView 还是无法抛弃的,目前最好的方式还是:方式3,我们以后切换图片加载库的时候,更新继承的父类,替换功能实现类就行,虽然还是要硬性改动代码,但是只涉及到这个 自定义 view,范围只有一处,也算是可以接受的。说真的未来新的库也是很有可能上自己的 view 的,使用原生 imageview 的话可是实现不了太多功能的。

功能封装


前面说了各个图片加载库的差异性很大,尤其期中涉及到了 view 层,不单单是功能实现层。所以我们要仔细思考如何能做的易扩展,好维护。

看了几个实现:

  • GSYImageLoader
    这个实现可以做到 Glide 和 Fresco 来回切换,但是没有解决 view 的问题。优点在于功能封装的不错
  • 一种使用 Fresco 非侵入式加载图片的方式
    使用了 Fresco 提供的 DraweeHolder 来实现的自定义 view,跑了下 demo ,没啥问题,当然也是 demo 中都是使用的常用功能,这种方式我只找到这一个开源的demo,虽然文档中写了支持自定义 view ,但是也说了需要处理不少问题,容易给自己挖坑。所以我觉得编码能力强的同学可以研究一下,普通的开发者先不要尝试了

GSYImageLoader


这个实现可以做到 Glide 和 Fresco 来回切换,但是没有解决 view 的问题。优点在于功能封装的不错,类设计很情绪,库是用 kotlin 编写的。

  • GSYLoadOption
    把图片加载中 view 的各种状态,设置封装到这个 option 类中
  • GSYImageLoaderManager
    负责初始化,确定和切换具体的图片加载库类型
  • GSYImageConst
    各种状态值,静态参数
  • GSYImageLoader
    图片加载的功能接口,下面是实现
interface GSYImageLoader {

    /**
     * 加载图片
     * @param loadOption 加载图片配置
     * @param target 加载目标对象,ImageView or SimpleDraweeView
     * @param callback 加载回调
     * @param extendOption 额外配置接口
     */
    fun loadImage(loadOption: GSYLoadOption, target: Any?, callback: Callback?, extendOption: ExtendedOptions? = null)

    /**
     * 清除缓存
     * @param type GSYImageConst,清除类型
     */
    fun clearCache(type: Int = GSYImageConst.CLEAR_DISK_CACHE)

    /**
     * 清除指定缓存
     * @param type GSYImageConst,清除类型
     * @param loadOption 加载图片配置
     */
    fun clearCacheKey(type: Int = GSYImageConst.CLEAR_DISK_CACHE, loadOption: GSYLoadOption)

    /**
     * 是否已经缓存到本地
     * @param loadOption 加载图片配置
     * @param extendOption 额外配置接口
     * @return Boolean 是否已经缓存到本地
     */
    fun isCache(loadOption: GSYLoadOption, extendOption: GSYImageLoader.ExtendedOptions? = null): Boolean

    /**
     * 获取本地缓存
     * @param loadOption 加载图片配置
     * @param extendOption 额外配置接口
     * @return File
     */
    fun getLocalCache(loadOption: GSYLoadOption, extendOption: GSYImageLoader.ExtendedOptions? = null): File?

    /**
     * 获取本地缓存bitmap
     * @param loadOption 加载图片配置
     * @param extendOption 额外配置接口
     * @return Bitmap
     */
    fun getLocalCacheBitmap(loadOption: GSYLoadOption, extendOption: GSYImageLoader.ExtendedOptions? = null): Bitmap?


    /**
     * 获取本地缓存大小
     * @return Long
     */
    fun getCacheSize(): Long?


    /**
     * 下载图片
     * @param loadOption 加载图片配置
     * @param callback 加载回调
     * @param extendOption 额外配置接口
     * @return Bitmap
     */
    fun downloadOnly(loadOption: GSYLoadOption, callback: GSYImageLoader.Callback?, extendOption: GSYImageLoader.ExtendedOptions? = null)

    /**
     * 额外配置支持
     */
    interface ExtendedOptions {
        /**
         * @param option 配置对象
         * Glide    com.bumptech.glide.request.RequestOptions
         * Picasso  com.squareup.picasso.RequestCreator
         * Fresco   com.facebook.imagepipeline.request.ImageRequestBuilder
         */
        fun onOptionsInit(option: Any?)
    }

    /**
     * 回调接口
     */
    @UiThread
    interface Callback {
        fun onStart()

        fun onSuccess(result: Any?)

        fun onFail(error: Exception?)
    }
}

Fresco 代码封装看这篇,API 言简意赅,使用简单,封装优秀,思路简单

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343