Переменная «runnable» должна быть инициализирована

Почему Котлин жалуется на это:

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

Solutions Collecting From Web of "Переменная «runnable» должна быть инициализирована"

Котлин считает свойство неинициализированным до конца его инициализатора, поэтому он не может использоваться внутри собственного инициализатора даже в лямбдах. Эта семантика аналогична ограничению использования локальной переменной внутри ее инициализатора .

Существует несколько способов:

  • Используйте выражение объекта, которое позволяет ссылаться на this объявленного объекта:

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

    Это хорошо работает только для интерфейсов в качестве замены для лямбда и совсем не совсем красиво.

  • Используйте lateinit var или делегированное свойство с 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() 
  • Внедрить и использовать самостоятельную ссылку для инициализаторов самостоятельно:

     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