android - 如何在协程中制作敬酒消息?
问题描述
环境
假设我有一个创建 toast 消息的函数
fun makeToast(success: Boolean){
if (success){
Toast.makeText(someContext, "Success", Toast.LENGHT_SHORT).show()
}
}
此功能用于另一个暂停的功能,例如
suspend fun makeRequest(){
success = doSomeHTTPRequest()
makeToast(success)
}
当我使用这个函数来执行请求时,我将在 IO 的协程中执行它,例如
CoroutineScope(IO).launch{
makeRequest()
}
问题
像上面建议的那样做以结束:
java.lang.NullPointerException: Can't toast on a thread that has not called Looper.prepare()
问题
解决此问题的最佳做法是什么?直接的方法是更改makeToast
为
fun makeToast(success: Boolean){
if (success){
Looper.prepare()
Toast.makeText(someContext, "Success", Toast.LENGHT_SHORT).show()
Looper.loop()
}
}
然而,这感觉很尴尬,因为这意味着该函数makeToast
已经知道它可能不会在主线程中被调用,这在我看来会产生奇怪的耦合。
解决方案
Main
在运行只允许从主线程调用的代码时,您需要指定使用调度程序。我想从错误消息中可以看出,如果它们有一个准备好的 Looper,你可以使用其他线程,但是如果你只是从主线程中专门制作 Toasts,它会容易得多。
此外,适当组合的挂起函数应该可以安全地从任何调度程序调用。您永远不必指定 Dispatcher 来调用挂起函数。当您调用阻塞代码并因此需要指定适当的后台调度程序时,或者调用需要在主线程上调用的函数时,应指定调度程序。
因此,您可以(IO)
从launch
通话中删除。在您的函数中调用阻塞或主独占函数的位置指定您的调度程序makeRequest
:
suspend fun makeRequest(){
val success = withContext(Dispatchers.IO) {
doSomeHTTPRequest()
}
withContext(Dispatchers.Main) {
makeToast(success)
}
}
推荐阅读
- javascript - 启动机器人时出现“Client.js”错误和 Sqlite 错误
- io - I/O 系统,计算周期寄存器和预分频值
- javascript - 通过变量更改嵌入文本
- amazon-web-services - 来自不同 AWS 账户的交叉堆栈引用
- c# - C# Visual Studio 2010 与 2019 中的计时器实现
- r - 根据值选择每个组中的行
- python - 如何从matlab矩阵.mat中提取相机校准参数到python numpy数组?
- php - 配置 Nginx 以提供 WEBP 图像?
- python - 将列表附加到列表
- java - 主页上的第二个按钮未启动新活动