Запись таймера с помощью Handler в Котлине

Я пытаюсь реализовать таймер Android в Kotlin, который будет запускать событие в определенный промежуток времени. Я не хочу использовать TimerTask из-за его документированных недостатков ( см. Здесь ), и хотя есть потенциально другие способы сделать это, я бы хотел использовать Handler / Runnable в цикле после задержки. В Java это возможно, поскольку Runnable может ссылаться на себя в инициализаторе, однако в Kotlin это кажется невозможным:

private fun startBoutiqueRefreshTimer(delayMs: Long) { val handler = Handler() val runnable = Runnable() { EventManager.post(BoutiqueRefreshTimerEvent()) handler.postDelayed(runnable, delayMs) } handler.postDelayed(runnable, delayMs) } 

потому что runnable не может быть разрешен во внутреннем вызове postDelayed. Вероятно, Котлин предотвращает переменные ссылки из своих собственных инициализаторов.

Что было бы хорошим решением этой проблемы, все еще используя подход Handler / Runnable?

Вы можете перемещать процедуру, которую вы хотите выполнять периодически, в отдельной функции:

 val runnable = Runnable { doJob() } fun doJob() { EventManager.post(BoutiqueRefreshTimerEvent()) handler.postDelayed(runnable, delayMs) } 

Обратите внимание, что переменная runnable должна быть доступна в пределах функции doJob (), что означает, что она должна быть членом класса, если вы находитесь в классе / объекте.

Вы также можете использовать что-то вроде этого:

 private fun startBoutiqueRefreshTimer(delayMs: Long) { Handler().apply { val runnable = object : Runnable { override fun run() { EventManager.post(BoutiqueRefreshTimerEvent()) postDelayed(this, delayMs) } } postDelayed(runnable, delayMs) } } 

Я использовал здесь функцию apply() для упрощения переменной Handler и выражения объекта, чтобы разрешить ссылаться на Runnable.

Как вы можете видеть, когда я использовал выражение объекта для инициализации Runnable (вместо лямбда), я могу использовать this для ссылки на объект Runnable .

Это будет работать

 val updateHandler = Handler() val runnable = Runnable { updateDisplay() // some action(s) } updateHandler.postDelayed(runnable, 5000). private fun updateDisplay() { Do actions } 

Или, если вы не слишком знакомы с Kotlin, напишите свой код и преобразуйте свой код Android в Kotlin, используя Ctrl + Alt + Shift + K ".