【问题标题】:Why recomposition doesn't happen when TextFieldValue changes为什么当 TextFieldValue 更改时不会发生重组
【发布时间】:2022-11-14 10:03:06
【问题描述】:

我的视图模型

val names =
    listOf(
        "valeria",
        "Daniela",
        "Isabella",
        "Liam",
        "Noah",
        "Jack",
        "Oliver",
        "Ava",
        "Sophia",
        "Amelia"
    )

private val _namesList = MutableStateFlow(names)
val namesList = _namesList.asStateFlow()


fun getFilteredNames(state: MutableState<TextFieldValue>) {
    viewModelScope.launch {
        val searchedText = state.value.text
        _namesList.value =
            if (searchedText.isEmpty()) {
                names
            } else {
                val resultList = ArrayList<String>()
                for (item in names) {
                    if (item.lowercase(Locale.getDefault())
                            .contains(searchedText.lowercase(Locale.getDefault()))
                    ) {
                        resultList.add(item)
                    }
                }
                Log.d("List: ", namesList.value.toString())
                resultList
            }
    }
}

由于某种原因,重组不会发生。

 val viewModel: MainViewModel = viewModel()
 val names = viewModel.namesList.collectAsState()
    LazyColumn(
        modifier = Modifier
            .fillMaxSize().background(MaterialTheme.colors.background)
    ) {
        items(names.value.size) {
            SearchListItem(names.value[it]) {}
        }
    }

【问题讨论】:

    标签: android android-jetpack-compose kotlin-stateflow compose-recomposition


    【解决方案1】:

    一旦我有同样的问题(你可以看到它和其他一些答案here)。如果很快,流仅在您向其发出新对象时更新(与最后发出的项目具有不同的哈希码)。并且您正在更新相同的列表,然后尝试将其传递给流程。如果您将创建列表的副本并发出此副本,那么一切都会正常,因为它已经是另一个对象

    【讨论】:

    • Log.d("List: ", namesList.hashCode().toString()) 每次 TextFieldValue 更改时显示不同的哈希码,但重组仍然没有发生!
    【解决方案2】:

    所以我不确定你是如何使用这个回调来获取更多项目的。简化它会像:

    val mutableNamesList = MutableStateFlow(listOf<String>())
    val namesList = mutableNamesList.asStateFlow()
    
    @Composable
    fun NamesList() {
        val coroutineScope = rememberCoroutineScope()
        var text by remember { mutableStateOf("") }
        TextField(value = text, onValueChange = { newTextValue ->
            text = newTextValue
            coroutineScope.launch {
                mutableNamesList.value = ( mutableNamesList.value + newTextValue)
            }
        })
       val list =  namesList.collectAsState().value
        LazyColumn {
            items(list) { item ->
                Text(text = item)
            }
        }
    }
    

    只是,我使用了这个导入:

    import androidx.compose.foundation.lazy.items
    

    【讨论】:

    • 这正是我所做的,名称列表在 ViewModel 中的 TextFieldValue 更改时得到更新,但在调用 val names = viewModel.namesList.collectAsState() 后,更改不会反映在 LazyColumn 中
    • 然后尝试将 val names = viewModel.namesList.collectAsState().value 移到 LazyColumn 之外
    • 它已经在 LazyColumn 之外
    • 我从 TopAppBar 移动了搜索视图,重组工作正常,但是如何使用 TopAppBar 中的 SearchView (TextField) 进行重组
    • 我不知道你的代码结构是什么。可能这就是你需要的developer.android.com/jetpack/compose/state#state-hoisting
    猜你喜欢
    • 2012-11-24
    • 2020-08-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-07
    相关资源
    最近更新 更多