Kotlin为什么抱怨这个:
class MyActivity : Activity {
private var handler:Handler = Handler()
private var runnable: Runnable = Runnable {
/* Do something very important */
handler.postDelayed(this@MyActivity.runnable, 5000)
}
}
编译器抱怨说,线路中的Variable 'runnable' must be initialized
是由处理程序再次发布的。
这在纯Java中起作用:
private Handler handler = new Handler();
private Runnable runnable = new Runnable() {
@Override
public void run() {
handler.postDelayed(runnable, 5000);
}
};
答案 0 :(得分:16)
Kotlin认为属性未初始化直到其初始化程序结束,因此它不能在自己的初始化程序中使用,即使在lambdas中也是如此。这种语义类似于local variable usage inside its initializer的限制。
有几种解决方法:
使用object expression可以引用声明对象的this
:
private var runnable: Runnable = object : Runnable {
override fun run() {
/* Do something very important */
handler.postDelayed(this, 5000)
}
}
这只适用于作为lambdas的替代品的接口,并且不是很完美。
lateinit var
使用delegated property或Delegates.notNull()
:
private lateinit var runnable: Runnable
init {
runnable = Runnable {
/* Do something very important */
handler.postDelayed(runnable, 5000)
}
}
相同的初始化程序将使用此声明:
private var runnable: Runnable by Delegates.notNull()
自行实施和使用self-reference for initializers:
class SelfReference<T>(val initializer: SelfReference<T>.() -> T) {
val self: T by lazy {
inner ?: throw IllegalStateException("Do not use `self` until initialized.")
}
private val inner = initializer()
}
fun <T> selfReference(initializer: SelfReference<T>.() -> T): T {
return SelfReference(initializer).self
}
然后你可以写点像
private var runnable: Runnable = selfReference {
Runnable {
/* Do something very important */
handler.postDelayed(self, 5000)
}
}
答案 1 :(得分:1)
您也可以使用
private var runnable: Runnable = Runnable {
/* Do something very important */
handler.postDelayed(runnable(), 5000)
}
private fun runnable() = runnable