android - 如何在 Jetpack Compose 中处理一次性操作?

标签 android android-jetpack-compose

备注 - 这个问题和 this one 差不多.
如果有的话,我正在寻找更好的方法。
根据 Android Docs ,

Once the transient message has been shown, the UI needs to notify the ViewModel of that, causing another UI state update:


例如,当我在单击按钮时显示 Toast 消息时,UI 是否应该通知 ViewModel 成功显示 Toast?
这是处理 toast 、 snackbar 等一次性操作的最佳方法吗?
示例代码,
@Composable
fun OneShotOperation(
    viewmodel: OneShotOperationViewModel = viewModel(),
) {
    val context = LocalContext.current

    LaunchedEffect(
        key1 = viewmodel.toastMessage,
    ) {
        if (viewmodel.toastMessage.isNotBlank()) {
            Toast.makeText(
                context,
                viewmodel.toastMessage,
                Toast.LENGTH_SHORT,
            ).show()
            viewmodel.toastMessage = "" // Is this the correct way?
        }
    }

    Button(
        onClick = {
            viewmodel.toastMessage = "Sample Toast"
        },
    ) {
        Text(text = "Show Toast")
    }
}

class OneShotOperationViewModel : ViewModel() {
    var toastMessage by mutableStateOf(
        value = "",
    )
}
如果我删除这条线,viewmodel.toastMessage = "" // Is this the correct way?toast 只显示一次,随后按下按钮不会显示 toast,因为可变状态没有改变。

最佳答案

我更喜欢使用 SharedFlow对于这样的工作:

class OneShotOperationViewModel : ViewModel() {
    private val _toastMessage = MutableSharedFlow<String>()
    val toastMessage = _toastMessage.asSharedFlow()

    fun sendMessage(message: String) {
        viewModelScope.launch {
            _toastMessage.emit(message)
        }
    }
}

@Composable
fun TestScreen() {
    val context = LocalContext.current

    val viewModel = viewModel<OneShotOperationViewModel>()
    LaunchedEffect(Unit) {
        viewModel
            .toastMessage
            .collect { message ->
                Toast.makeText(
                    context,
                    message,
                    Toast.LENGTH_SHORT,
                ).show()
            }
    }
    Button(
        onClick = {
            viewModel.sendMessage("Sample Toast")
        },
    ) {
        Text(text = "Show Toast")
    }
}
请注意,如果您在 collect 时从另一个 View 发送消息没有运行,当你最终启动它时它不会显示 toast 。它不存储值,它只将它传递给当前连接的所有收集器。

关于android - 如何在 Jetpack Compose 中处理一次性操作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71033789/

相关文章:

android - 将 flutter Painter 转换为 compose

Android 动画嵌套 fragment

Android:搜索 Intent 不起作用

java - Intent JSONObject 到另一个 Activity

kotlin - Google map Compose MyLocationButton 未显示

android - Jetpack Compose 中复选框中的透明复选标记

android - JetPack Compose Pager 的 onPageSelected 回调

android - 如何在可组合的屏幕中使用协同程序?

java - Android - NullPointerException - 无法启动 Activity ComponentInfo

java - 如何存储多个字节数组