Làm thế nào để gọi một chức năng sau khi trì hoãn trong Kotlin?


Câu trả lời:


134

Bạn có thể sử dụng Lịch trình

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

ví dụ (cảm ơn @Nguyen Minh Bình - đã tìm thấy nó ở đây: http://jamie.mccrindle.org/2013/02/exploring-kotlin-st Chuẩn-l Library-part -.html.html )

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

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

16
Cảm ơn! Siêu dễ. Tìm thấy một ví dụ ở đây jamie.mccrindle.org/2013/02/ từ Timer("SettingUp", false).schedule(500) { doSomething() }
Nguyễn Minh Bình

9
Nó không biên dịch, nếu bạn thêm hai lần nhập này: nhập java.util.Timer và nhập kotlin.concien.schedule
Tùy biến

3
@Matias Elorriaga, đối với tôi, việc đưa nó vào một tệp thương hiệu mới không được biên dịch, thậm chí thêm các tùy chỉnh nhập khẩu đã nói
Sulfkain

3
bạn không cần phải đặt nó vào một tập tin, phương pháp đó là một phần của stdlib, hãy theo liên kết trong dòng đầu tiên của câu trả lời,
Matias Elorriaga

3
Ban đầu tôi nghĩ rằng điều này sẽ không được biên dịch ngay cả sau khi nhập kotlin.concurrent.schedule, bởi vì Kotlin chỉ phàn nàn về sự không phù hợp chữ ký, nhưng sau đó tôi nhận ra rằng tôi đang cố gắng vượt qua một Int thay vì Long. Nó biên dịch sau khi sửa nó.
Joe Lapp

178

Ngoài ra còn có một tùy chọn để sử dụng Handler -> postDelayed

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

18
Vui lòng thêm rằng nó chỉ khả dụng trên Android, vì câu hỏi yêu cầu phương pháp kotlin chung (mặc dù nó có thẻ Android)
Yoav Sternberg

5
Nó không mang tính xây dựng từ phía bạn. Kết quả là khi người dùng sẽ tìm kiếm thẻ android có thể nghĩ rằng đây là câu trả lời sai.
Bogdan Ustyak

9
Đối với Android, sử dụng Trình xử lý tốt hơn Bộ đếm thời gian: stackoverflow.com/questions/20330355/timertask-or-handler
woprandi

Tôi nghĩ rằng, bạn nên thêm một mã để loại bỏ các trình xử lý sau khi kết thúc hoạt động / đoạn.
CoolMind

Điều này sẽ không chạy trên luồng UI nếu bạn dự định làm điều đó.
AndroidDev

93

Nhiều cách

1. Sử dụng Handlerlớp học

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

2. Sử dụng Timerlớp học

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

Ngắn hơn

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

Ngắn nhất

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

3. Sử dụng Executorslớp học

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

1
và bạn nghĩ đâu là giải pháp tốt nhất ở đây?
Tamim Attafi

1
Có lẽ là người đầu tiên sử dụng Handler. Xem stackoverflow.com/a/40339630/1159930
Markymark

36

Bạn phải nhập hai thư viện sau:

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

và sau đó sử dụng nó theo cách này:

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

27

Bạn có thể launchmột coroutine, delaysau đó gọi hàm:

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

Nếu bạn ở bên ngoài một lớp hoặc đối tượng GlobalScopedự phòng để cho coroutine chạy ở đó, nếu không thì nên thực hiện CoroutineScopetrong lớp xung quanh, cho phép hủy tất cả các coroutine liên quan đến phạm vi đó nếu cần.


Cảm ơn! Thật kỳ lạ, các xác chết đó chỉ được đề cập trong năm 2018.
CoolMind

@coolMind họ ổn định từ vài tháng nay, vì vậy họ còn khá mới ...
Jonas Wilms

Vâng, từ tháng Mười-tháng Mười Một, nhưng đã tồn tại trước đó.
CoolMind

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

1
Bạn có thể vui lòng giải thích cho tôi tại sao tôi cần phải viết "timerTask" thay vì chỉ niềng răng không?
Hugo Passos

2
Tôi nghĩ bạn làm. Timer.schedule()mong đợi TimerTasknhư là đối số đầu tiên của nó. kotlin.concurrent.timerTask()kết thúc lambda đã cho trong một TimerTaskví dụ. Xem tại đây: kotlinlang.org/api/latest/jvm/stdlib/kotlin.concản/iêu
Blieque 27/03/18

Ngoài ra, ví dụ đã cho có thể được cô đọng thành một dòng nếu Timerđối tượng sẽ không được sử dụng nhiều lần, ví dụ : Timer().schedule(timerTask { ... }, 3000). Một tùy chọn thân thiện hơn với Kotlin cũng có sẵn; xem câu trả lời của jonguer.
Blieque 27/03/18

10

Một ví dụ đơn giản để hiển thị bánh mì nướng sau 3 giây :

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

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

1
tôi có thể hủy cuộc gọi không?
Eduardo Oliveros

6

Nếu bạn đang tìm kiếm cách sử dụng chung, đây là gợi ý của tôi:

Tạo một lớp có tên là Run:

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

Và sử dụng như thế này:

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

Bạn có thể đơn giản hóa điều này dưới dạng phần mở rộng
Vlad

@Ogulcan, nhiều kotlinic lamda Run.after(1000) { toRun() }. Tôi có đúng không
binrebin

0

Tôi khuyên bạn nên sử dụng SingleThread vì bạn không phải giết nó sau khi sử dụng. Ngoài ra, phương thức " stop ()" không được dùng trong ngôn ngữ Kotlin.

private fun mDoThisJob(){

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

    }, 1, 1, TimeUnit.SECONDS)
}

Hơn nữa, bạn có thể sử dụng nó cho công việc định kỳ. Nó rất hữu ích. Nếu bạn muốn thực hiện công việc cho mỗi giây, bạn có thể đặt vì các tham số của nó:

Executors.newSingleThreadSchediatedExecutor (). CalendarAtFixedRate (Lệnh Runnable, dài initDelay, thời gian dài, đơn vị TimeUnit);

Các giá trị TimeUnit là: NANOSECONDS, MICROSECONDS, MILLISECONDS, SECONDS, MINUTES, GIỜ, NGÀY.

@canerkaseler

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.