首先,我的英语不好。对不起
我想像下面这样展示祝酒消息
但它不起作用。
'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")
}
}
希望一切顺利
您无法从协程中获取 LocalContext,因为协程
launch
块不是可组合项。在声明 Button 之前使用它,并确保应用程序 Context 是安全的,因为您在协程中使用的 context 可能比可组合项的寿命长。
@Composable
fun DogButton() {
val appContext = LocalContext.applicationContext
androidx.compose.material.Button(onClick = {
//...
Toast.makeText(appContext, ...
出于代码组织的目的,在 ViewModel 或其他类似类中进行此类工作可能更合适。您可以使用 AndroidViewModel 并使用其应用程序引用来获取上下文。那么这个点击监听只需要调用ViewModel函数即可
此代码:
CoroutineScope(Dispatchers.Main).launch {
通常是一种反模式,无论您是否在可组合项中。这意味着您正在创建一个不受限制的协程——无论您的应用程序的关联部分是否已经消失和销毁,它都会一直存在直到完成,因此它是内存泄漏和其他资源浪费的来源。
通常,您总是使用具有适当生命周期的适当 CoroutineScope 启动协程。当您从中启动的工作已过时时将被取消。
您的代码可能是个例外,因为它根本不与可组合项或 Activity UI 交互。它只启动一个 Toast,这是应用程序范围内的一个 UI。所以如果你真的想在 Activity 关闭的情况下显示这个 Toast,那么以这种方式启动你的协程就可以了。
我认为在这种情况下,您应该使用 GlobalScope 来清楚地表明这是一个不属于可能取消它的生命周期的协程。它实际上是一样的,但你不会创建一个冗余的 CoroutineScope。
Composable
函数不应用于调用 API 或执行任何处理密集型工作。 (Source)您调用 API 并在失败时显示 Toast 的要求可以在 ViewModel
和该按钮的相应 onClick
内处理。
要在 Composable 函数内的协程范围内显示 toast,您可以使用 CoroutineScope.launch 函数和 CoroutineExceptionHandler 来捕获协程中发生的任何异常。
举个例子:
fun MyComposableFunction() {
val coroutineScope = rememberCoroutineScope()
Button(onClick = {
coroutineScope.launch(CoroutineExceptionHandler { _, throwable ->
// handle exception, e.g. log or display error message
Toast.makeText(LocalContext.current, "An error occurred: ${throwable.message}", Toast.LENGTH_SHORT).show()
}) {
// run your coroutine code here
launch {
// your coroutine code here
Toast.makeText(LocalContext.current, "Toast message", Toast.LENGTH_SHORT).show()
}
}
}) {
Text("Show Toast")
}
} 在这个例子中,我们首先通过调用 rememberCoroutineScope() 获得一个 CoroutineScope。然后我们使用这个范围在点击按钮时启动一个新的协程。我们传入一个 CoroutineExceptionHandler 来捕获协程中发生的任何异常。在启动块内,我们可以运行协程代码,在本例中,它使用 Toast.makeText 函数显示 Toast 消息。请注意,我们使用 LocalContext.current 来获取用于显示 Toast 消息的当前上下文。
这只是一个示例,说明如何在可组合函数的协程范围内显示 Toast 消息。在 Compose 中有很多方法可以处理协程和异常,因此请务必选择最适合您的用例的方法。