Glide用Kotlin应该这样封装(二)

3,076 阅读2分钟

Kotlin应该这样写系列:

SharedPreferences用Kotlin应该这样写

Glide用Kotlin应该这样封装(一)

更加coil化

上篇Glide用Kotlin应该这样封装(一)中,我初步完成了使用扩展函数,用kotlin可选择参数的方式封装gilde,但是在用可选择参数实现回调接口时候,接口的实现类会让代码变的非常难看,那么怎么优化呢?先看下最终实现结果

// URL
imageView.load("https://www.example.com/image.jpg")
// Resource
imageView.load(R.drawable.image)
//回调和进度监听
imageView.load("https://www.example.com/image.jpg") {
    placeHolderResId = R.drawable.placeholder
    transformation = arrayOf(GrayscaleTransformation())
    progressListener { isComplete, percentage, bytesRead, totalBytes ->
        //加载进度
    }
    requestListener {
        onSuccess {
        }
        onFail {
        }
    }
}

优化回调为DSL

1、接口只有一个回调函数可以直接使用lamba表达式实现回调的简写

view.setOnClickListener { view ->
    //TODO
}
//回调参数仅仅只有一个还可以省略
view.setOnClickListener {
    //TODO
}

2、接口中含有多个回调函数,都会使用object对象表达式来实现的

requestListener = object : OnImageListener {
    override fun onSuccess(drawable: Drawable?) {
    }
    override fun onFail(msg: String?) {
    }
},

那么如何让多个回调的方式,变成如下这样更加kotlin风格呢:

requestListener {
    onSuccess {//TODO}
    onFail {//TODO}
}

ImageExt调用DSL化

  • 改造加载回调
class OnImageListener {
    internal var onFailAction: ((String?) -> Unit)? = null
    internal var onSuccessAction: ((Drawable?) -> Unit)? = null

    fun onFail(action: (String?) -> Unit) {
        onFailAction = action
    }

    fun onSuccess(action: (Drawable?) -> Unit) {
        onSuccessAction = action
    }
}

/*** 加载监听*/
var requestListener: OnImageListener? = null
    private set
fun requestListener(listener: OnImageListener.() -> Unit) {
    requestListener = OnImageListener().also(listener)
}
//使用
requestListener {
    onSuccess {//TODO}
    onFail {//TODO}
}
  • 改造进度加载,利用typealias起别名
//原来接口形式
interface OnProgressListener {
    fun onProgress(isComplete: Boolean, percentage: Int, bytesRead: Long, totalBytes: Long)
}

//由于只有一个方法可以直接用lamba表达式实现回调的简写,但是默认提示还是使用 object方法。再次优化
//给函数起别名 便于调用和书写,参数过多难懂,别名就代表了这个函数
typealias OnProgressListener = ((isComplete: Boolean, percentage: Int, bytesRead: Long, totalBytes: Long) -> Unit)?

/*** 网络进度监听器*/
var onProgressListener: OnProgressListener = null
    private set
fun progressListener(listener: OnProgressListener) {
    this.onProgressListener = listener
}
//使用
progressListener { isComplete, percentage, bytesRead, totalBytes ->
    //加载进度
}
  • 提供DSL编写方式
/**模仿 coil**/
fun ImageView.load(load: Any?, options: (ImageOptions.() -> Unit)? = null) {
    val imageOptions = ImageOptions().also {
        it.res = load
        it.imageView = this
    }
    GlideImageLoader.loadImage(options?.let {
        imageOptions.also(options)
    } ?: imageOptions)
}
// 只有这么几行 没错对比可选参数方式超长的代码 这也太简洁了
//使用
iv.load("https://www.test.png")
// holder
iv.load("https://www.test.png"){
    placeHolderResId = R.color.black
}
// holder
iv.load("https://www.test.png"){
    placeHolderResId = R.color.black
    transformation = arrayOf(GrayscaleTransformation(), CircleWithBorderTransformation(borderWidth = 0, borderColor = 0))
    progressListener { isComplete, percentage, bytesRead, totalBytes ->
        //加载进度
    }
    requestListener {
        onSuccess {}
        onFail {}
    }
}

总结

参考:如何让你的回调更具Kotlin风味

项目开源地址:github.com/forJrking/I…

缺点:由于添加进度回调让Glide使用了注解配置,如果你需要自定义配置需要拉取项目改动后自己编译