我有一个ViewModel,它使用Flow从我的Room数据库获取Note对象:

var uiState by mutableStateOf(NoteUiState())
        private set


    private fun getNoteById(argument: Int) {
        viewModelScope.launch {
            try {
                repository.getNoteById(argument).collect { note ->
                    uiState = NoteUiState(note = note)
                }
            } catch (e: Exception) {
                uiState = NoteUiState(error = true)
            }
        }
    }

备注类:

@Entity(tableName = "notes")
data class Note(
    @PrimaryKey(autoGenerate = true) val id: Int = 0,
    @ColumnInfo(name = "title") val title: String = "",
    @ColumnInfo(name = "text") val text: String = "",
) {
    override fun toString() = title
}

这种方法工作得很好,直到我try 用Note对象的值作为它们的缺省值来创建一个可变字符串,这样我就可以更新2个TextField组合:

@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun Note(
    note: DataNote,
    isNewNote: Boolean,
    createNote: (DataNote) -> Unit,
    updateNote: (DataNote) -> Unit,
    back: () -> Unit,
    trued: String,
) {

    var title by remember { mutableStateOf(note.title) }
    var content by remember { mutableStateOf(note.text) }
    TextField(
        value = title,
        onValueChange = { title = it },
        modifier = Modifier
            .fillMaxWidth(),
        placeholder = { Text(text = "Title") },
        colors = TextFieldDefaults.textFieldColors(
            containerColor = Color.Transparent
        )
    )
    TextField(
        value = content,
        onValueChange = { content = it },
        modifier = Modifier
            .fillMaxWidth(),
        placeholder = { Text(text = "Content") },
        colors = TextFieldDefaults.textFieldColors(
            containerColor = Color.Transparent
        )
    )
}

由于某些原因,第一次调用Note对象时它是空的,所以我想要一种更新标题和内容变量的方法.

Note对象本身更新时没有问题,但是标题和内容变量永远不会从初始值更改.如何更新标题和内容变量,同时使它们适用于文本字段?

推荐答案

我了解了如何在从对象获取初始值的同时使Textfield起作用.问题是,Note对象在第一次调用时被调用为空,因此muableStateFlow没有获得初始值.

首先,我必须将实际状态作为MuableStateFlow传递给我的Composable:

@Composable
private fun Note(
    state: MutableStateFlow<NoteUiState>,
    createNote: (DataNote) -> Unit,
    updateNote: (DataNote) -> Unit,
    back: () -> Unit
) {
...

接下来,我只需通过调用collectAsState()来获取Note对象:

val currentNote = state.collectAsState().value.note

最后,只需在Textfield的值中传递CurentNote对象的文本和标题,并在onValueChange上通过一个副本更新状态对象本身:

这是完整的解决方案:

@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun Note(
    state: MutableStateFlow<NoteUiState>,
    createNote: (DataNote) -> Unit,
    updateNote: (DataNote) -> Unit,
    back: () -> Unit
) {
    val currentNote = state.collectAsState().value.note
    Column(Modifier.fillMaxSize()) {
        TextField(
            value = currentNote.title,
            onValueChange = {
                state.value = state.value.copy(note = currentNote.copy(title = it))
                            },
            modifier = Modifier
                .fillMaxWidth(),
            placeholder = { Text(text = "Title") },
            colors = TextFieldDefaults.textFieldColors(
                containerColor = Color.Transparent
            )
        )
    }
}

我不确定这是不是一个干净的解决方案,但这是它对我起作用的唯一方式,谢谢你的反馈,我们总是欢迎对这种方法的意见.

Android相关问答推荐

在Android Studio Iguana上运行示例代码时,Gradle Build错误

如何使禁用状态下的material 3按钮与启用状态下的 colored颜色 相同?

如何解决Android Studio中的in fragment问题

如何使用Jetpack Compose使水平pager 显示离屏页面?

如何检测HitTest是否命中给定的网格对象?

Kotlin DSL:为什么我可以从Play Store获取发布版本的日志(log)?

Android Jetpack Compose调用view-model函数仅一次

Jetpack编写错误(java.lang.NoSuchMethodError:无接口方法startRestartGroup)

在androidStudio中,如何使用带有ResolutionStrategy的ResolutionSelector而不是setTargetResolve()?

触发PurchasesUpdatedListener回调时,billingClient.launchBillingFlow之前设置的成员变量丢失

Android Kotlin - 计费 - 从应用内购买获取productId

为什么 Android Studio 中的 theme.xml 目录没有任何原色

Android Studio Relay插件(版本0.3.07)错误

Android Studio 在 list 文件中已经声明了活动类,但仍出现无法找到明确的活动类的错误

在事件中使用 Context/Toast 时不需要的重组 - Jetpack Compose

如何像 XML 一样在 Compose Android Studio 中折叠/展开小部件代码区域/区域

错误:构建 react-native 应用程序时包 com.facebook.react.bridge 不存在

为什么官方文档用大写字母表示val变量?

预览必须是顶级声明或具有默认构造函数的顶级类

Android WebView 没有在第一次页面完成时从本地存储读取数据?