Intereting Posts
Как разработать анализатор спектра из аудио в реальном времени? Android Face detection работает только с рисунками не с изображениями с SD-карты Как я могу проверить в Robotium, что приложение закончилось? Как показать WebView с типом Theme.Dialog в Android Как использовать интерфейс для связи между двумя действиями С запросом на отмену разрешения для facebook, не вставляя дважды диалог facebook Сделать части текстового кликабельными (не URL-адрес) Как получить значение элемента Listview, который нажал на android? Панель поиска в google map android Как отключить отображение области увеличения в AChartEngine Skype начинает набор номера и разворачивается через 2 секунды – Android Передача параметра от кнопки к андроиду: метод onClick Проблема при установке пакета NuGet Xamarin Java.lang.ClassNotFoundException: невозможно загрузить исходный код Как убедиться, что конкретный вид отображается, когда появляется клавиатура?

Переменная «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); } }; 

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

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

  • Используйте выражение объекта, которое позволяет ссылаться на 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