如何在 Composable 函数中的协程中显示 Toast 消息?

huangapple go评论57阅读模式
英文:

How to show a toast msg on coroutine in composable fun?

问题

抱歉,我不能执行代码翻译请求。

英文:

First of all, My english is bad. sorry about that

I wanna show a toast msg like below

but it not working.

'this' should be context but it always CoroutineScope

LocalContext.current not also working

is it bad practice? if yes plz explain and give me good answer!

@Composable
fun DogButton() {

    androidx.compose.material.Button(onClick = {

        CoroutineScope(Dispatchers.Main).launch {

            try {

                val response = ApiAdapter.apiClient.getRandomDogImage()

                if (response.isSuccessful && response.body() != null) {

                } else {

                    Toast.makeText(this, "Error", Toast.LENGTH_SHORT) // it occur compile error. 


                }

            } catch (exception : Exception) {


            }
        }

    /*TODO*/ }) {

        Text(text = "Get a Dog Image")
    }
}

I hope it will be good

答案1

得分: 1

你不能从你的协程中获取 LocalContext,因为协程 launch 块不是 Composable。在声明 Button 之前使用它,并获取应用程序的 Context 以确保安全,因为你正在在可能超出 Composable 生命周期的协程中使用上下文。

@Composable
fun DogButton() {
    val appContext = LocalContext.applicationContext

    androidx.compose.material.Button(onClick = {
        //...
        Toast.makeText(appContext, ...

出于代码组织的目的,更合适的做法可能是在 ViewModel 或类似的类中执行这种工作。你可以使用 AndroidViewModel 并使用其 Application 引用来获取 Context。然后,此点击侦听器只需调用 ViewModel 函数。

这段代码:

CoroutineScope(Dispatchers.Main).launch {

通常是一种反模式,无论你是否在 Composable 中使用它。这意味着你正在创建一个不受限制的协程,它将一直存在,直到完成,而不管你的应用程序的相关部分是否已经终止和销毁,因此它可能导致内存泄漏和其他资源浪费。

通常情况下,你应该始终使用具有适当生命周期的适当 CoroutineScope 启动协程。这将在启动协程的工作过时时被取消。

也许你的代码是一个例外,因为它根本不与 Composable 或 Activity UI 交互。它只是启动一个 Toast,这是应用程序范围内的 UI。所以,如果你真的想在 Activity 关闭时显示此 Toast,那么以这种方式启动协程是可以的。

在这种情况下,我认为你应该使用 GlobalScope,以明确表示这是一个不属于可能会取消它的生命周期的协程。这在效果上是相同的,但你不会创建多余的 CoroutineScope。

英文:

You can't get the LocalContext from your coroutine, since a coroutine launch block is not a Composable. Use it before declaring your Button, and get the application Context to be safe, since you're using the context in a coroutine that might outlive the composable.

@Composable
fun DogButton() {
    val appContext = LocalContext.applicationContext

    androidx.compose.material.Button(onClick = {
        //...
        Toast.makeText(appContext, ...

It is probably more appropriate to do this kind of work in a ViewModel or other similar class for code-organization purposes. You could use an AndroidViewModel and use its Application reference to get a Context. Then this click listener only needs to call the ViewModel function.

This code:

CoroutineScope(Dispatchers.Main).launch {

is usually an antipattern, regardless of whether you're in a Composable. It means you are creating an unconfined coroutine--it will live until completion regardless of whether the associated part of your app is already gone and destroyed, and therefore it is a source of memory leaks and other wasted resources.

Usually, you always start a coroutine using an appropriate CoroutineScope that has a an appropriate lifetime. One that will be cancelled when the work you're launching from it is obsolete.

Possibly, your code is an exception because it isn't interacting with the composable or Activity UI at all. It only launches a Toast, which is a UI at the scope of the application. So if you really want to show this Toast even if the Activity is closed, then it would be OK to launch your coroutine this way.

It is my opinion that in this case, you should use GlobalScope to clearly indicate that this is a coroutine that is not part of a lifecycle that might cancel it. It is effectively the same but you won't be creating a redundant CoroutineScope.

答案2

得分: 0

Composable 函数不应用于调用 API 或进行任何处理密集型的工作。 (来源) 你的需求,即在失败时调用 API 并显示 Toast,可以在 ViewModel 内部以及该按钮的相应 onClick 中处理。

英文:

Composable functions should not be used to call APIs or do any processing intensive work. (Source) Your requirement of calling an API and showing a Toast on failure can be handled inside a ViewModel and the respective onClick of that button.

huangapple
  • 本文由 发表于 2023年4月17日 14:22:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/76032199.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定