变量'runnable'必须被初始化

为什么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); } }; 

Kotlin认为一个属性没有被初始化,直到它的初始化器结束,所以它不能在自己的初始化器中使用,即使在lambdas中也是如此。 这种语义与其初始化程序中局部变量使用的局限性相似。

有几个解决方法:

  • 使用对象表达式可以让你引用this声明的对象:

     private var runnable: Runnable = object : Runnable { override fun run() { /* Do something very important */ handler.postDelayed(this, 5000) } } 

    这只适用于作为lambda的替代接口,并不是非常漂亮。

  • 使用lateinit varDelegates.notNull()的委托属性 :

     private lateinit var runnable: Runnable init { runnable = Runnable { /* Do something very important */ handler.postDelayed(runnable, 5000) } } 

    相同的初始化器将与这个声明一起工作:

     private var runnable: Runnable by Delegates.notNull() 
  • 自行实现和使用初始值设定项的自引用 :

     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) } } 

你也可以使用

 private var runnable: Runnable = Runnable { /* Do something very important */ handler.postDelayed(runnable(), 5000) } private fun runnable() = runnable