在我的项目中使用Android Studio中的“BottomN航空”模板,我面临着如何更新片段的文本视图的问题。
AndroidStudio中的“BottomN航空”模板有一个HomeFragment. kt,我可以从以下位置设置文本视图:
覆盖乐趣onViewCreated(视图:视图,保存InstanceState:捆绑包?){…}
但是,如果我这样启动CoroutineScope():
CoroutineScope(Dispatchers.IO).launch {
test_function()
}
我无法从test_function()中更新文本视图。
这里特别失败:
private suspend fun client(address : String, port: Int) {
val connection: Socket
try {
connection = Socket(address, port)
}
catch(e: Exception) {
textView.text = "Error: Socket exception: " + e
return
}
val writer = connection.getOutputStream()
writer.write(1)
val reader = Scanner(connection.getInputStream())
textView.text = "test string"
...
}
它在以下行失败:
textView.text = "test string"
通过崩溃。
我应该从test_function()中使用findViewById()来获取我的文本视图的句柄(?)或其他东西吗?即使这是正确的解决方案,我也会遇到以下错误:
Unresolved reference: findViewById
我需要做什么才能从CoroutineScope调用的函数中更新text View?
您没有共享堆栈跟踪,但我假设问题是您从主线程以外的线程更新TextView,这是不允许的。
按照惯例,挂起
函数应该总是在内部将工作委托给适当的调度程序。因此,如果上面的代码中有任何阻塞函数调用,您应该将它们包装在with Context(Dispatchers.IO) { }
中,同样,您应该将修改视图的代码部分包装在with Context(Dispatcher. Main) { }
中。例如:
private suspend fun client(address : String, port: Int) = withContext(Dispatchers.IO) {
val connection: Socket
try {
connection = Socket(address, port)
}
catch(e: Exception) {
withContext(Dispatchers.Main) { textView.text = "Error: Socket exception: " + e }
return
}
val writer = connection.getOutputStream()
writer.write(1)
val reader = Scanner(connection.getInputStream())
withContext(Dispatchers.Main) { textView.text = "test string" }
...
}
当您启动协程时,如果它只是调用挂起函数和非阻塞函数,则无需在那里指定调度程序,假设您已适当遵循上述约定。
此外,您很少需要像在代码中那样创建自己的协程范围。在这种情况下,如果由于配置更改或应用程序挂起并恢复后重新创建了您的Fragment,您的协程可能仍在运行,这会泄漏内存,并且如果您尝试访问Context,可能会导致崩溃。您应该使用viewLiftycleOwner. liftycleScope
在Fragment中启动您的协程。当片段视图被销毁时,它会自动停止。