Как вызвать функцию после задержки в Kotlin?

Как заголовок, есть ли способ вызвать функцию после задержки (например, 1 секунда) в Kotlin?

15 ответов

Решение

Вы можете использовать Расписание

inline fun Timer.schedule(
    delay: Long, 
    crossinline action: TimerTask.() -> Unit
): TimerTask (source)

пример (спасибо @Nguyen Minh Binh - нашел его здесь: http://jamie.mccrindle.org/2013/02/exploring-kotlin-standard-library-part-3.html)

Timer("SettingUp", false).schedule(500) { 
   doSomething()
}

Также есть возможность использовать Handler -> postDelayed

 Handler().postDelayed({
                    //doSomethingHere()
                }, 1000)

Много способов

1. Использование Handler учебный класс

Handler().postDelayed({
    TODO("Do something")
    }, 2000)

2. Использование Timer учебный класс

Timer().schedule(object : TimerTask() {
    override fun run() {
        TODO("Do something")
    }
}, 2000)

Более короткие

Timer().schedule(timerTask {
    TODO("Do something")
}, 2000)

самый короткий

Timer().schedule(2000) {
    TODO("Do something")
}

3. Использование Executors учебный класс

Executors.newSingleThreadScheduledExecutor().schedule({
    TODO("Do something")
}, 2, TimeUnit.SECONDS)

Вы могли бы launch сопрограмма, delay это, а затем вызвать функцию:

 launch {
   delay(1000)
   yourFn()
 }

Вы должны импортировать следующие две библиотеки:

import java.util.*
import kotlin.concurrent.schedule

и после этого используйте его следующим образом:

Timer().schedule(10000){
    //do something
}
val timer = Timer()
timer.schedule(timerTask { nextScreen() }, 3000)

Если вы используете более свежие API-интерфейсы Android, пустой конструктор Handler устарел, и вы должны включить Looper. Вы можете легко пройти черезLooper.getMainLooper().

    Handler(Looper.getMainLooper()).postDelayed({
        //Your code
    }, 2000) //millis

Если вы находитесь во фрагменте с областью видимости viewModel, вы можете использовать сопрограммы Kotlin:

    myViewModel.viewModelScope.launch {
        delay(2000)
        // DoSomething()
    }

Простой пример показа тоста через 3 секунды:

fun onBtnClick() {
    val handler = Handler()
    handler.postDelayed({ showToast() }, 3000)
}

fun showToast(){
    Toast.makeText(context, "Its toast!", Toast.LENGTH_SHORT).show()
}

Если вы ищете универсальное использование, вот мое предложение:

Создать класс с именем как Run:

class Run {
    companion object {
        fun after(delay: Long, process: () -> Unit) {
            Handler().postDelayed({
                process()
            }, delay)
        }
    }
}

И используйте так:

Run.after(1000, {
    // print something useful etc.
})

Я предлагаю использовать корутину kotlin, и если вы хотите отменить ее. его простой и легкий вес.

      fun repeatFun(): Job {
    return coroutineScope.launch {  
        while(isActive) {
            //do your work here
            delay(1000)
        }
    }
}

//start the loop
val repeatFun = repeatRequest()

//Cancel the loop
repeatFun.cancel()

Другой способ создать избыточное задание, отличный от этого ; это не требует приостановки функции.

         val repeatableJob = CoroutineScope(Dispatchers.IO).launch {
        while (true) {
            delay(1000)
        }
    }

Отменить, когда вы закончите -repeatableJob.cancel()

Я рекомендовал использовать SingleThread, потому что вам не нужно его убивать после использования. Кроме того, в языке Котлин устарел методstop().

private fun mDoThisJob(){

    Executors.newSingleThreadScheduledExecutor().scheduleAtFixedRate({
        //TODO: You can write your periodical job here..!

    }, 1, 1, TimeUnit.SECONDS)
}

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

Executors.newSingleThreadScheduledExecutor(). ScheduleAtFixedRate(команда Runnable, длинная начальная задержка, длительный период, единица TimeUnit);

Значения TimeUnit: НС, МИКРОСЕКУНД, МИЛЛИСЕКУНД, СЕКУНД, МИНУТЫ, ЧАСЫ, ДНИ.

@canerkaseler

Я использую следующие функции:

      fun <T> delayedAsyncTask(delayMs: Long = 0, task: () -> T): ScheduledFuture<T> {
    return Executors
        .newSingleThreadScheduledExecutor()
        .schedule(Callable<T> { task() }, delayMs, TimeUnit.MILLISECONDS)
}

fun <T> asyncTask(task: () -> T) = delayedAsyncTask(0, task)

Вот модульный тест для отложенной функции. Использование возвращенного будущего, конечно, необязательно.

          @Test
    fun `delayed task work correctly`() {
        val future = delayedAsyncTask(1000) {
            "lambda returns hello world"
        }
        assertEquals(false, future.isDone)
        Thread.sleep(1100)
        assertEquals(true, future.isDone)
        assertEquals("lambda returns hello world", future.get())
    }

если вы вызываете функцию в пользовательском интерфейсе.

      Timer().schedule(1000) {
  activity?.runOnUiThread {
    doSomething()
  }
}
Другие вопросы по тегам