Kotlin:如何在不冻结UI的情况下延迟Android中的代码

时间:2019-01-24 14:18:54

标签: kotlin ui-thread background-thread

我正在尝试延迟我尝试过的Kotlin中的代码

Thread.sleep(1000)

但是它冻结了UI。

有人知道为什么会这样吗 以及如何在不冻结UI的情况下进行延迟?

6 个答案:

答案 0 :(得分:2)

您可以使用处理程序对象https://developer.android.com/reference/android/os/Handler

val handler = Handler()
val runnable = Runnable {
    // code which will be delayed  
}

handler.postDelayed(runnable, 1000)

1000以毫秒为单位的时间,应将其替换为您的值。

答案 1 :(得分:2)

出了什么问题

用法Thread.sleep(...)

  

Thread.sleep使当前线程在指定的时间段内暂停执行。这是使处理器时间可用于应用程序的其他线程或计算机系统上可能正在运行的其他应用程序的有效方法。

对于OP(原始张贴者/询问者)的说明:

  

它冻结了UI,有人知道为什么会这样吗?

如上所述,从Java的官方文档中可以看到,由于在主线程中调用了UI,因此您在UI中遇到了某种冻结。

主线程,或者如果您正在使用Android编写内容,通常将其称为 UI线程

  

在Android平台上,默认情况下,应用程序在一个线程上运行。该线程称为 UI线程。之所以常这样称呼,是因为该单个线程显示了用户界面并侦听用户与应用程序交互时发生的事件。

不使用多线程API(例如RunnableCoroutinesRxJava)的帮助,您将自动在 UI上调用Thread.sleep(1000)线程,这就是为什么您要经历这种“ UI冻结” 的原因,因为其他UI Operations由于调用了挂起而被阻止访问该线程。

  

以及如何延迟而不冻结ui?

利用可用API的多线程功能,到目前为止,最好从以下选项开始:

1。可运行

在Java中

// Import
import android.os.Handler;

// Use
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
  @Override
  public void run() {
     // do something after 1000ms
  }
}, 1000);

在科特林

// Import
import android.os.Handler;

// Use
val handler = Handler()
handler.postDelayed({
     // do something after 1000ms
}, 1000)

2。 Kotlin协程

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

// Use
Timer().schedule(1000){
    // do something after 1 second
}

3。 RxJava

// Import
import io.reactivex.Completable
import java.util.concurrent.TimeUnit

// Use
Completable
     .timer(1, TimeUnit.SECONDS)
     .subscribeOn(Schedulers.io()) // where the work should be done
     .observeOn(AndroidSchedulers.mainThread()) // where the data stream should be delivered
     .subscribe({
          // do something after 1 second
     }, {
          // do something on error
     })

目前,在这三种方法中,RxJava是多线程处理和处理应用程序中大量数据流的一种方式。但是,如果您刚开始,最好先尝试一下基础知识。

参考

答案 2 :(得分:1)

GlobalSocpe.launch(Dispatchers.MAIN){
delay(5000)
}

这是您要求的代码部分。但是对于您的解决方案,请先了解

启动

异步

类似地,您应该了解

的其他值

调度员

答案 3 :(得分:0)

如果您不想冻结UI,则需要从 MainThread 中执行代码。
有很多方法可以做到。一些例子:

线程

Thread {
    Thread.sleep(1000)
    // Your code
}.start()

Rx

您需要https://github.com/ReactiveX/RxJava

Flowable.timer(1000, TimeUnit.MILLISECONDS)
    .subscribeOn(AndroidSchedulers.mainThread())
    .subscribe { 
        // Your code
    }

Kotlin协程

GlobalScope.launch { // launch new coroutine in background and continue
    delay(1000L) // non-blocking delay for 1 second (default time unit is ms)
    println("World!") // print after delay
}

参考:https://kotlinlang.org/docs/reference/coroutines-overview.html

文档:

答案 4 :(得分:0)

  

CreateCloudTableClient

     

使当前正在执行的线程进入睡眠状态(暂时停止   执行)指定的毫秒数,[...]

请参阅https://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html#sleep(long)

如果您是在代码运行所在的默认线程UI线程上调用的,则它将停止并等待。

在纯Kotlin中,您应该使用coroutine

Thread.sleep(1000);

如果您正在编写Android应用程序,则可以使用Handler和Androidx获得特别好的语法:

import kotlinx.coroutines.*

fun main() {
    GlobalScope.launch { // launch new coroutine in background and continue
        delay(1000L) // non-blocking delay for 1 second (default time unit is ms)
        println("World!") // print after delay
    }
    println("Hello,") // main thread continues while coroutine is delayed
    Thread.sleep(2000L) // block main thread for 2 seconds to keep JVM alive
}

答案 5 :(得分:0)

说明:

Thread.sleep(1000)在UI线程上运行,该UI线程负责呈现应用并使其具有响应能力。

sleep调用将使其在1秒钟内无响应,因为它阻止了进一步的执行。

该怎么做:

AsyncTask是处理长时间运行的任务的一种好方法,因为它可以清楚地区分UI线程和辅助线程。

  

AsyncTask允许正确且轻松地使用UI线程。这个班   允许您执行后台操作并在   UI线程,而无需操纵线程和/或处理程序。

示例:

class LongRunningTask : AsyncTask<Unit, Unit, String>() {

     override fun doInBackground(vararg units: Unit): String {

         // runs on separate thread

         Thread.sleep(1000) // some long running operation

         return "Hello"
     }

     override fun onPostExecute(result: String) {
        // This runs on the main thread again
        // and views can be updated with the result
     }
 }

您可以像这样使用它:

LongRunningTask().execute()