Callback,异步回调结果,相比大家都不会太陌生。那么在 Kotlin 中我们又是如何解决这个问题的呢?(本文只从原来从事Java开发现在转Kotlin的角度来讲)
没有 Kotlin 的时代
举个例子:需要访问网络,更新界面,如果用Java来写,一般我们分三步:
- 新建一个callback的interface:
interface NetworkCallback {
void onCallback(..)
}
- 请求网络,调用callback回调给上层
void getRes(NetworkCallback:callback){
....
callback.onCallback(..)
....
}
- 使用
getRes(new NetworkCallback(){
void onCallback(..){
//update UI
}
} )
只要需要异步回调,我们都需要去新建一个callback的interface接口类,然后用的时候需要实现下这个接口,只要虽然看上去很清晰,但是写起来步骤很繁琐。
是否可以简化成一个{}就能搞定呢?答案当然是可以的,不过只能跟着我来一起看Kotlin了的。
有了 Kotlin 的时代
上面的例子可以去掉第一步了的,直接去写我们真正需要关心的网络请求部分了的:
- 请求网络,调用callback ( 闭包 )回调给上层
fun getRes(callback: (Any)->Unit){
....
callback(...)
....
}
- 使用
getRes(){
println(it)
}
是不是几行代码就搞定了的?减少了太多的没必要的编码时间。
Kotlin 为什么要设计出来这个闭包的概念呢?
存在即合理的原则,那么为什么要这么设计呢?如何设计的呢?
从上面的例子,Kotlin极大的提高了我们编码效率,那么自然存在是合理的,编码最终的期望值是交给机器人一样的道理,越简单越受人青睐。可能做IDE的公司,实在是心疼我们开发者吧,每天要去创建那么多没必要的中间类吧。
那Kotlin到底是怎么实现这个的呢?
看一下Kotlin-runtime这个Jar包中的<Functions.kt>类,很有意思,提供了总计达23个接口,从无参到22个参数:
/** A function that takes 0 arguments. */
public interface Function0<out R> : Function<R> {
/** Invokes the function. */
public operator fun invoke(): R
}
...
/** A function that takes 22 arguments. */
public interface Function22<in P1, in P2, in P3, in P4, in P5, in P6, in P7, in P8, in P9, in P10, in P11, in P12, in P13, in P14, in P15, in P16, in P17, in P18, in P19, in P20, in P21, in P22, out R> : Function<R> {
/** Invokes the function with the specified arguments. */
public operator fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13, p14: P14, p15: P15, p16: P16, p17: P17, p18: P18, p19: P19, p20: P20, p21: P21, p22: P22): R
}
那么事实上�上面那个例子中的Kotlin闭包,当然使用Java去调用这个闭包,你就会发现,就是由他来帮我们完成了工作,那问题来了,如果我们的参数超过了22怎么办呢?纯Kotlin代码调用是没有问题的:
fun testF23(callback:(String,String,String,String,String,String,String
,String,String,String,String,String,String,String,
String,String,String,String,String,String,String,String,
String)->Unit){
}
testF23 { a, b, c, d, e, f, g, h, i, j, k, l, m, n, p14, p15, p16, p17, p18, p19, p20, p21, p22 -> }
但是Java调用就无能为力了的,虽然编译器会提示new Function23,但是找不到这个类,即使Kotlin去写,编译依然会报错:'Exception in thread "main" java.lang.NoClassDefFoundError: kotlin/Function23'
当然实际工作中,闭包要回调这么多参数,似乎也不科学吧。
总结
Kotlin 大多数情况下,如果仅仅是一个异步回调结果,我们再也不需要去创建多余的interface类了的,直接一个闭包(Any..)-> .. 解决问题,极大的提供了工作效率。
网友评论