Jak wywołać funkcję po opóźnieniu w Kotlinie?


Odpowiedzi:


134

Możesz użyć harmonogramu

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

przykład (dzięki @Nguyen Minh Binh - znalazłem go tutaj: http://jamie.mccrindle.org/2013/02/exploring-kotlin-standard-library-part-3.html )

import java.util.Timer
import kotlin.concurrent.schedule

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

16
Dzięki! Super łatwe. Przykład znalazłem tutaj jamie.mccrindle.org/2013/02/…Timer("SettingUp", false).schedule(500) { doSomething() }
Nguyen Minh Binh

9
Kompiluje się, jeśli dodasz te dwa importy: import java.util.Timer i import kotlin.concurrent.schedule
Customizer

3
@Matias Elorriaga, dla mnie, umieszczanie tego na nowym pliku marki nie kompiluje się, nawet dodając import Customizer powiedział
Sulfkain

3
nie musisz umieszczać go w pliku, ta metoda jest częścią standardowej biblioteki, podążaj za linkiem w pierwszej linii odpowiedzi,
Matias Elorriaga

3
Początkowo myślałem, że to się nie skompiluje nawet po zaimportowaniu kotlin.concurrent.schedule, ponieważ Kotlin tylko narzekał na niezgodność podpisu, ale potem zdałem sobie sprawę, że próbuję przekazać Int zamiast Long. Został skompilowany po poprawieniu tego.
Joe Lapp

178

Istnieje również opcja użycia Handler -> postDelayed

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

18
Dodaj, że jest dostępny tylko na Androida, ponieważ pytanie dotyczy ogólnej metody kotlin (chociaż ma tag Androida)
Yoav Sternberg

5
To nie jest konstruktywne z Twojej strony. W rezultacie, gdy użytkownicy będą przeszukiwać tag Androida, mogą pomyśleć, że to zła odpowiedź.
Bogdan Ustyak

9
W przypadku Androida lepiej jest użyć programu Handler niż Timer: stackoverflow.com/questions/20330355/timertask-or-handler
woprandi

Myślę, że powinieneś dodać kod do usuwania programów obsługi po zakończeniu działania / fragmentu.
CoolMind

Nie będzie to działać w wątku interfejsu użytkownika, jeśli zamierzałeś to zrobić.
AndroidDev

93

Wiele sposobów

1. Korzystanie z Handlerklasy

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

2. Korzystanie z Timerklasy

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

Krótszy

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

Najkrótsza

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

3. Korzystanie z Executorsklasy

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

1
i jakie według ciebie jest najlepsze rozwiązanie tutaj?
Tamim Attafi

1
Prawdopodobnie pierwszy korzystający z Handlera. Zobacz stackoverflow.com/a/40339630/1159930
Markymark

36

Musisz zaimportować następujące dwie biblioteki:

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

a potem użyj go w ten sposób:

Timer().schedule(10000){
    //do something
}

27

Mógłbyś launchcoroutine, delaya następnie wywołać funkcję:

 /*GlobalScope.*/launch {
   delay(1000)
   yourFn()
 }

Jeśli jesteś poza klasą lub obiektem, GlobalScopedołącz poprzednik, aby pozwolić programowi działać w tym miejscu, w przeciwnym razie zaleca się zaimplementowanie CoroutineScopew otaczającej klasie, co pozwala w razie potrzeby anulować wszystkie procedury powiązane z tym zakresem.


Dzięki! Dziwne, że o korepetycjach wspomniano dopiero w 2018 roku.
CoolMind

@coolMind są stabilne od kilku miesięcy, więc są całkiem nowe ...
Jonas Wilms

Tak, od października do listopada, ale istniało wcześniej.
CoolMind

23
val timer = Timer()
timer.schedule(timerTask { nextScreen() }, 3000)

1
Czy możesz mi wyjaśnić, dlaczego muszę napisać „timerTask” zamiast samych nawiasów klamrowych?
Hugo Passos

2
Myśle że robisz. Timer.schedule()oczekuje, że TimerTaskjako pierwszy argument. kotlin.concurrent.timerTask()zawija podaną lambdę w TimerTaskinstancji. Zobacz tutaj: kotlinlang.org/api/latest/jvm/stdlib/kotlin.concurrent/…
Blieque

Również podany przykład można skondensować do jednej linii, jeśli Timerobiekt nie będzie używany więcej niż raz, np Timer().schedule(timerTask { ... }, 3000).. Dostępna jest również opcja bardziej przyjazna Kotlinowi; zobacz odpowiedź Jonguera.
Blieque

10

Prosty przykład pokazujący toast po 3 sekundach :

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

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

1
czy mogę anulować połączenie?
Eduardo Oliveros

6

Jeśli szukasz ogólnego zastosowania, oto moja sugestia:

Utwórz klasę o nazwie Run:

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

I użyj w ten sposób:

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

Możesz to uprościć jako funkcję rozszerzenia
Vlad

@Ogulcan, bardziej kotlinic lamda Run.after(1000) { toRun() }. Czy mam rację
binrebin

0

Polecam używanie SingleThread, ponieważ nie musisz go zabijać po użyciu. Ponadto metoda „ stop ()” jest przestarzała w języku Kotlin.

private fun mDoThisJob(){

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

    }, 1, 1, TimeUnit.SECONDS)
}

Ponadto możesz go używać do pracy okresowej. To jest bardzo użyteczne. Jeśli chcesz wykonywać pracę na każdą sekundę, możesz ustawić jej parametry:

Executors.newSingleThreadScheduledExecutor (). ScheduleAtFixedRate (polecenie Runnable, long initialDelay, long period, unit TimeUnit);

Wartości TimeUnit to: NANOSECONDS, MICROSECONDS, MILISECONDS, SECONDS, MINUTES, HOURS, DAYS.

@canerkaseler

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.