如何在协程中制作吐司消息?
How to make a toast message in a coroutine?
设置
假设我有一个创建 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 来调用挂起函数。当您调用阻塞代码并因此需要指定适当的后台调度程序时,或者在调用需要在主线程上调用的函数时,应指定调度程序。
因此,您可以从 launch
通话中删除 (IO)
。在你的 makeRequest
函数中,在调用阻塞函数或 main-exclusive 函数的地方指定你的调度程序:
suspend fun makeRequest(){
val success = withContext(Dispatchers.IO) {
doSomeHTTPRequest()
}
withContext(Dispatchers.Main) {
makeToast(success)
}
}
在应用程序中显示 Toast 消息的最佳方式
Step 1 创建kotlin class ToastMessage.kt 并编写代码
import android.content.Context
import android.widget.Toast
fun Context.tost(message: String) = Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
/*call this method to any class*/
this.tost("successfuly show message")
设置
假设我有一个创建 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 来调用挂起函数。当您调用阻塞代码并因此需要指定适当的后台调度程序时,或者在调用需要在主线程上调用的函数时,应指定调度程序。
因此,您可以从 launch
通话中删除 (IO)
。在你的 makeRequest
函数中,在调用阻塞函数或 main-exclusive 函数的地方指定你的调度程序:
suspend fun makeRequest(){
val success = withContext(Dispatchers.IO) {
doSomeHTTPRequest()
}
withContext(Dispatchers.Main) {
makeToast(success)
}
}
在应用程序中显示 Toast 消息的最佳方式 Step 1 创建kotlin class ToastMessage.kt 并编写代码
import android.content.Context
import android.widget.Toast
fun Context.tost(message: String) = Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
/*call this method to any class*/
this.tost("successfuly show message")