android 如何在协同程序中显示吐司消息?

llew8vvj  于 2023-04-18  发布在  Android
关注(0)|答案(2)|浏览(115)

首先,我的英语不好,很抱歉
我想显示一个像下面这样的吐司词
但它不工作。
'this'应该是上下文,但它始终是CoroutineScope
LocalContext.current也不起作用
这是不好的做法吗?如果是,请解释并给予我一个好的答案!

@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")
    }
}

我希望它会很好

daupos2t

daupos2t1#

你不能从你的协程中获取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启动协程。当您从其中启动的工作过时时,该生命周期将被取消。
你的代码可能是一个例外,因为它根本没有与可组合或Activity UI交互。它只启动吐司,这是应用程序范围内的UI。所以如果你真的想在Activity关闭时显示这个Toast,那么以这种方式启动你的协程是可以的。
我的观点是,在这种情况下,你应该使用GlobalScope来清楚地表明这是一个协同程序,它不是可能取消它的生命周期的一部分。它实际上是相同的,但你不会创建一个冗余的CoroutineScope。

ffx8fchx

ffx8fchx2#

Composable函数不应用于调用API或执行任何处理密集型工作。(来源)您调用API和在失败时显示吐司的需求可以在ViewModel和该按钮的相应onClick中处理。

相关问题