简体   繁体   English

如何在协程中制作敬酒消息?

[英]How to make a toast message in a coroutine?

Setting环境

Let's say I have a function that creates a toast message假设我有一个 function 可以创建一个 toast 消息

fun makeToast(success: Boolean){
    if (success){
        Toast.makeText(someContext, "Success", Toast.LENGHT_SHORT).show()
    }
}

This function is used in another function that is suspended eg这个 function 用于另一个被暂停的 function 例如

suspend fun makeRequest(){
    success = doSomeHTTPRequest()
    makeToast(success)
}

When I'm using this function to execute the request I will do it in a coroutine for IO for example ie当我使用这个 function 执行请求时,我将在 IO 的协程中执行它,例如,即

CoroutineScope(IO).launch{
    makeRequest()
}

Issue问题

Doing it like proposed above ends in:像上面建议的那样做以结束:

java.lang.NullPointerException: Can't toast on a thread that has not called Looper.prepare()

Question问题

What is the best practice to fix this?解决此问题的最佳做法是什么? The straight forward way would be to change makeToast to直接的方法是将makeToast更改为

fun makeToast(success: Boolean){
    if (success){
        Looper.prepare()
        Toast.makeText(someContext, "Success", Toast.LENGHT_SHORT).show()
        Looper.loop()
    }
}

However this feels akward since this means that the function makeToast already knows that it might not be called in the main thread which creates a weird coupling in my opinion.然而,这感觉很尴尬,因为这意味着 function makeToast已经知道它可能不会在主线程中调用,这在我看来会产生奇怪的耦合。

You need to specify using the Main dispatcher when running code that is only allowed to be called from the main thread.当运行只允许从主线程调用的代码时,您需要指定使用Main调度程序。 I suppose from the error message it is suggesting you can use other threads if they have a prepared Looper, but it's a lot easier if you simply make Toasts exclusively from the main thread.我想从错误消息中可以看出,如果它们有一个准备好的 Looper,你可以使用其他线程,但如果你只是从主线程中专门制作 Toasts,它会容易得多。

Also, a properly composed suspend function should be safe to call from any dispatcher.此外,正确组合的挂起 function 应该可以安全地从任何调度程序调用。 You should never have to specify a Dispatcher to call a suspend function.您永远不必指定 Dispatcher 来调用挂起 function。 A dispatcher should be specified when you are calling blocking code and therefore need to specify an appropriate background dispatcher, or when calling a function that is required to be called on the main thread.当您调用阻塞代码并因此需要指定适当的后台调度程序时,或者调用需要在主线程上调用的 function 时,应指定调度程序。

So, you can remove (IO) from your launch call.因此,您可以从launch调用中删除(IO) Specify your dispatchers at the point where the blocking or main-exclusive functions are being called, which is in your makeRequest function:在您的makeRequest function 中指定调用阻塞或主独占函数的位置的调度程序:

suspend fun makeRequest(){
    val success = withContext(Dispatchers.IO) { 
        doSomeHTTPRequest()
    }
    withContext(Dispatchers.Main) {
        makeToast(success)
    }
}

best way to show Toast message in app Step 1 create a kotlin class ToastMessage.kt and write code在应用程序中显示 Toast 消息的最佳方式步骤 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")

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM