วิธีการเรียกฟังก์ชั่นหลังจากล่าช้าใน Kotlin?


คำตอบ:


134

คุณสามารถใช้กำหนดการ

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 )

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

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

16
ขอบคุณ! ง่ายสุด ๆ พบตัวอย่างที่นี่jamie.mccrindle.org/2013/02/… Timer("SettingUp", false).schedule(500) { doSomething() }
เหงียนมินห์บินห์

9
มันจะคอมไพล์ถ้าคุณเพิ่มการนำเข้าสองรายการนี้: import java.util.Timer และ import kotlin.concurrent.schedule
Customizer

3
@Matias Elorriaga สำหรับฉันการวางไฟล์แบรนด์ใหม่นี้ไม่ได้รวบรวมแม้แต่การเพิ่มการนำเข้า Customizer กล่าว
Sulfkain

3
คุณไม่จำเป็นต้องวางมันลงบนไฟล์วิธีนี้เป็นส่วนหนึ่งของ stdlib ตามลิงค์ในบรรทัดแรกของคำตอบ
Matias Elorriaga

3
ฉันคิดว่าสิ่งนี้จะไม่สามารถรวบรวมได้แม้หลังจากนำเข้าkotlin.concurrent.scheduleเพราะ Kotlin เพียงแค่บ่นว่ามีลายเซ็นที่ไม่ตรงกัน แต่จากนั้นฉันก็รู้ว่าฉันกำลังพยายามผ่าน Int แทน Long มันรวบรวมหลังจากแก้ไขแล้ว
Joe Lapp

178

นอกจากนี้ยังมีตัวเลือกให้ใช้ Handler -> postDelayed

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

18
โปรดเพิ่มว่ามีให้เฉพาะบน Android เนื่องจากคำถามถามหาวิธี kotlin ทั่วไป (แม้ว่าจะมีแท็ก Android)
Yoav Sternberg

5
มันไม่สร้างสรรค์จากด้านข้างของคุณ ดังนั้นเมื่อผู้ใช้จะค้นหาแท็ก android อาจคิดว่านี่เป็นคำตอบที่ผิด
Bogdan Ustyak

9
สำหรับ Android จะดีกว่าถ้าใช้ Handler กว่า Timer: stackoverflow.com/questions/20330355/timertask-or-handler
woprandi

ฉันคิดว่าคุณควรเพิ่มรหัสสำหรับการลบตัวจัดการหลังจากเสร็จสิ้นกิจกรรม / ส่วน
CoolMind

สิ่งนี้จะไม่ทำงานบนเธรด UI หากคุณต้องการทำเช่นนั้น
AndroidDev

93

มีหลายวิธี

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)

1
และคุณคิดว่าอะไรคือทางออกที่ดีที่สุดที่นี่
Tamim Attafi

1
อาจเป็นคนแรกที่ใช้ตัวจัดการ ดูstackoverflow.com/a/40339630/1159930
Markymark

36

คุณต้องนำเข้าสองไลบรารีต่อไปนี้:

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

และหลังจากนั้นใช้ในวิธีนี้:

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

27

คุณสามารถlaunchcoroutine delayได้แล้วเรียกใช้ฟังก์ชัน:

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

หากคุณอยู่นอกคลาสหรือวัตถุเสริมGlobalScopeเพื่อให้ coroutine ทำงานที่นั่นมิฉะนั้นจะแนะนำให้ใช้CoroutineScopeในคลาสโดยรอบซึ่งช่วยให้สามารถยกเลิก coroutines ทั้งหมดที่เกี่ยวข้องกับขอบเขตนั้นหากจำเป็น


ขอบคุณ! แปลก, coroutines ที่ถูกกล่าวถึงเฉพาะใน 2018.
CoolMind

@coolMind พวกเขามีความเสถียรตั้งแต่ไม่กี่เดือนดังนั้นพวกเขาจึงค่อนข้างใหม่ ...
Jonas Wilms

ใช่ตั้งแต่เดือนตุลาคมถึงพฤศจิกายน แต่มีมาก่อน
CoolMind

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

1
คุณช่วยอธิบายฉันหน่อยได้ไหมว่าทำไมฉันถึงต้องเขียน "timerTask" แทนการจัดฟัน?
Hugo Passos

2
ฉันคิดว่าคุณทำ Timer.schedule()คาดว่าจะTimerTaskเป็นอาร์กิวเมนต์แรก kotlin.concurrent.timerTask()ตัดแลมบ์ดาที่ระบุไว้ในTimerTaskอินสแตนซ์ ดูที่นี่: kotlinlang.org/api/latest/jvm/stdlib/kotlin.concurrent/ …
Blieque

นอกจากนี้ตัวอย่างที่กำหนดสามารถย่อให้เป็นหนึ่งบรรทัดได้หากTimerวัตถุนั้นจะไม่ถูกใช้มากกว่าหนึ่งครั้งเช่นTimer().schedule(timerTask { ... }, 3000). ตัวเลือกที่เป็นมิตรกับ Kotlin ก็มีให้เช่นกัน ดูคำตอบของ jonguer
Blieque

10

ตัวอย่างง่ายๆเพื่อแสดงขนมปังหลังจาก3 วินาที :

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

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

1
ฉันจะยกเลิกการโทรได้ไหม?
Eduardo Oliveros

6

หากคุณกำลังมองหาการใช้งานทั่วไปนี่คือคำแนะนำของฉัน:

สร้างคลาสที่ชื่อว่าRun:

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

และใช้ดังนี้:

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

คุณสามารถลดความซับซ้อนนี้เป็นส่วนขยาย fucntion
Vlad

@Ogulcan, Run.after(1000) { toRun() }Lamda ฉันถูกต้อง
binrebin

0

ฉันแนะนำให้ใช้SingleThreadเพราะคุณไม่จำเป็นต้องฆ่ามันหลังจากใช้งาน นอกจากนี้เมธอด" stop ()" ยังเลิกใช้ในภาษา Kotlin

private fun mDoThisJob(){

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

    }, 1, 1, TimeUnit.SECONDS)
}

ยิ่งกว่านั้นคุณสามารถใช้มันสำหรับงานตามกำหนดเวลา มันมีประโยชน์มาก หากคุณต้องการทำงานในแต่ละวินาทีคุณสามารถตั้งค่าได้เนื่องจากพารามิเตอร์ของมัน:

Executors.newSingleThreadScheduledExecutor (). scheduleAtFixedRate (คำสั่ง Runnable, initialDelay ที่ยาว, ระยะเวลานาน, หน่วย TimeUnit);

ค่า TimeUnit คือ: NANOSECONDS, MICROSECONDS, MILLISECONDS, SECONDS, MINUTES, ชั่วโมง, DAYS

@canerkaseler

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.