android - 为什么协程在使用 setOnTouchListener 时会破坏我的应用程序?
问题描述
当用户触摸按钮时,我想调用一些代码。当用户停止按下时,应用程序应该停止向服务器发送信息 - 音频块。我想我应该使用协程。但屏幕冻结,应用程序中断。
override fun onTouch(v: View?, event: MotionEvent?): Boolean {
runBlocking {
var job : Job? = null
when (event?.action) {
MotionEvent.ACTION_DOWN -> {
val startTime = System.currentTimeMillis()
val job = launch(Dispatchers.Default) {
var nextPrintTime = startTime
var i = 0
while (isActive) { // cancellable computation loop
// print a message twice a second
if (System.currentTimeMillis() >= nextPrintTime) {
println("job: I'm sleeping ${i++} ...")
nextPrintTime += 500L
}
}
}
}
MotionEvent.ACTION_UP -> {
println("main: I'm tired of waiting!")
job?.cancelAndJoin() // cancels the job and waits for its completion
println("main: Now I can quit.")
}
else ->
Log.i("else", "else")
}
}
return v?.onTouchEvent(event) ?: true
}
})
我想,在使用带有 MotionEvent 的 onTouch 时会发生这种情况。怎么了?我该怎么办?
解决方案
切勿runBlocking
在应用程序中使用。它用于测试或用于main
没有 GUI 的本机 Java 控制台应用程序中的功能。
runBlocking
违背了使用协程的目的并阻塞了调用它的线程,导致您的异步工作阻塞了线程。在这种情况下,由于它是从主线程调用的,它会阻塞主线程,因此您的 UI 将冻结,并且不可能接收到 ACTION_UP 信号。
要修复您当前的代码,您应该从而lifecycleScope
不是使用启动协程runBlocking
。此外,您job
在 ACTION_DOWN 部分中隐藏了变量。您需要使用现有变量才能在该范围之外取消它。
override fun onTouch(v: View, event: MotionEvent): Boolean {
var job : Job? = null
when (event.action) {
MotionEvent.ACTION_DOWN -> {
val startTime = System.currentTimeMillis()
job = lifecycleScope.launch {
var nextPrintTime = startTime
var i = 0
while (true) { // cancellable computation loop
yield()
// print a message twice a second
if (System.currentTimeMillis() >= nextPrintTime) {
println("job: I'm sleeping ${i++} ...")
nextPrintTime += 500L
}
}
}
}
MotionEvent.ACTION_UP -> {
lifecycleScope.launch {
println("main: I'm tired of waiting!")
job?.cancelAndJoin() // cancels the job and waits for its completion
println("main: Now I can quit.")
}
}
else -> Log.i("else", "else")
}
}
但是,您的用例似乎只是从该侦听器开始或停止某些事情。我不确定为此使用协程是否有意义。也许您处理上传工作的类会在内部使用协程,但不一定必须使用挂起函数来启动或停止。
推荐阅读
- javascript - 在 Selenium 中选择弹出窗口
- c# - 我无法在 Windows Server(Radius Server)上使用 winform C# 应用程序执行“netsh nps ...”命令
- monaco-editor - 位置集ModelMarker
- windows - 从网上下载 exe 并将其安装在一组服务器上
- c# - 解析完成前遇到流结束
- scala - Akka gRPC 绑定错误的端口号
- r - 在 R 中重新格式化条形图
- javascript - 限制 selectizeInput 中的下拉选项
- python - python中的sql查询-插入多个字典的值以分隔表列
- flutter - 使用 print 语句而不是 logging 语句对颤振/飞镖有任何性能影响吗?