![](/img/trans.png)
[英]can we use runblocking with coroutine for room queries in production?
[英]How can I use runblocking on button click
runblocking的目的是什么? 我可以在OnClickListener中使用它吗? 这里我在OnClickListener中使用了runblocking {}
这是我的代码
mBinding.ivAdd.setOnClickListener{
println("before" + Thread.currentThread().id)
runBlocking {
println("in async" + Thread.currentThread().id)
val job = launch {
// launch new coroutine and keep a reference to its Job
delay(1000L)
println("World!" + Thread.currentThread().id)
mBinding.tvNoDataFound.text = "test"
}
println("Hello,")
println("after hello" + Thread.currentThread().id)
delay(5000)
job.join() // wait until child coroutine completes
}
println("after runBlocking" + Thread.currentThread().id)
}
它显示这样的错误
12-20 14:46:31.387 26915-26915/ I/System.out: before1
12-20 14:46:31.399 26915-26915/ I/System.out: in async1
12-20 14:46:31.405 26915-26915/ I/System.out: Hello,
12-20 14:46:31.405 26915-26915/ I/System.out: after hello1
12-20 14:46:32.410 26915-26937/I/System.out: World!1561
12-20 14:46:32.422 26915-26937/ E/AndroidRuntime: FATAL EXCEPTION:
ForkJoinPool.commonPool-worker-2
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:6556)
at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:907)
at android.view.View.requestLayout(View.java:18728)
at android.view.View.requestLayout(View.java:18728)
at android.view.View.requestLayout(View.java:18728)
at android.view.View.requestLayout(View.java:18728)
at android.view.View.requestLayout(View.java:18728)
at android.view.View.requestLayout(View.java:18728)
at android.view.View.requestLayout(View.java:18728)
at android.view.View.requestLayout(View.java:18728)
at android.widget.TextView.checkForRelayout(TextView.java:7169)
at android.widget.TextView.setText(TextView.java:4347)
at android.widget.TextView.setText(TextView.java:4204)
at android.widget.TextView.setText(TextView.java:4179)
at MainActivity$onCreate$1$1$job$1.doResume(MainActivity.kt:164)
at kotlin.coroutines.experimental.jvm.internal.CoroutineImpl.resume(CoroutineImpl.kt:54)
at kotlinx.coroutines.experimental.DispatchTask.run(CoroutineDispatcher.kt:123)
at java.util.concurrent.ForkJoinTask$RunnableExecuteAction.exec(ForkJoinTask.java:1388)
at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:251)
at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:845)
at java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1674)
at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1629)
at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:108)
12-20 14:46:36.410 26915-26915/I/System.out: after runBlocking1
12-20 14:46:36.410 26915-26915/ I/Choreographer: Skipped 313 frames! The
application may be doing too much work on its main thread.
如果我使用launch(UI){}而不是launch {} ,它会提供如下输出
12-20 14:57:11.700 27338-27338/ I/System.out: before1
12-20 14:57:11.710 27338-27338/ I/System.out: in async1
12-20 14:57:11.714 27338-27338/ I/System.out: Hello,
12-20 14:57:11.714 27338-27338/ I/System.out: after hello1
12-20 14:57:16.718 27338-27338/ I/art: Note: end time exceeds epoch:
它不打印来自另一个协程的“世界”。
这是runblocking的另一个例子,它使用来自onCreate()的runblocking
println("before runblocking " + Thread.currentThread().id)
runBlocking {
println("in runblocking " + Thread.currentThread().id)
val job = launch(UI) {
println("In launch " + Thread.currentThread().id)
}
println("after launch " + Thread.currentThread().id)
}
println("after runBlocking " + Thread.currentThread().id)
上面代码的输出是
12-20 15:58:13.253 8588-8588/? I/System.out: before runblocking 1
12-20 15:58:13.266 8588-8588/? I/System.out: in runblocking 1
12-20 15:58:13.271 8588-8588/? I/System.out: after launch 1
12-20 15:58:13.273 8588-8588/? I/System.out: after runBlocking 1
12-20 15:58:13.363 8588-8588/? I/System.out: In launch 1
正如我们所期望的那样,“在runblocking之后”最后打印,但事实并非如此。 如果我使用job.join等待子协程的完成,代码是
println("before runblocking " + Thread.currentThread().id)
runBlocking {
println("in runblocking " + Thread.currentThread().id)
val job = launch(UI) {
println("In launch " + Thread.currentThread().id)
}
println("after launch " + Thread.currentThread().id)
job.join() // wait until child coroutine completes
}
println("after runBlocking " + Thread.currentThread().id)
上面代码的输出是
12-20 16:10:43.234 9194-9194/ I/System.out: before runblocking 1
12-20 16:10:43.249 9194-9194/ I/System.out: in runblocking 1
12-20 16:10:43.253 9194-9194/ I/System.out: after launch 1
那么runblocking的预期行为是什么? 我怎样才能使用runblocking?
即使您阻止了代码,操作mBinding.tvNoDataFound.text = "test"
在池工作线程上运行。
runBlocking
旨在将常规阻塞代码桥接到以挂起样式编写的库,以便在主函数和测试中使用。
在你的情况下,不应该使用它。 如果您需要执行后台工作,则不应阻止UI线程。 无论使用launch
还是launch(UI)
都会发生这种情况。 后者只是使所有内容在连接之前在同一个线程上运行并阻塞。
因此,尽量不要阻止UI线程并通过launch(UI)
或标准View.post {}
安排视图更新。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.