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 {}
}
}
总结
项目开源地址:github.com/forJrking/I…
缺点:由于添加进度回调让Glide使用了注解配置,如果你需要自定义配置需要拉取项目改动后自己编译