当前位置: 首页 > 知识库问答 >
问题:

从不同的可组合组件更新视图模型时,不可组合组件

裴俊智
2023-03-14

我正在使用Jetpack Compose开发Android应用程序。该应用程序显示项目列表。它还有一个包含搜索栏的顶部栏。

我们有3个组件:项目列表、搜索栏组件和应用程序栏(应用程序栏包含搜索栏)。

相同的 ViewModel 类注入到可组合列表和可组合搜索栏(使用 Hilt)中。视图模型具有以下项列表:

var项目由MutableStateOf

以及由搜索栏调用的搜索函数,用于过滤这些项目。

问题如下:搜索项目时,列表可组合无法重新组合。

铌:

    < li >我记录了搜索功能的输出,因此我确信该功能运行正常。 < li >当将可组合搜索栏放入包含项目列表的同一个可组合搜索栏时,搜索按预期进行。

因此,似乎只有当搜索栏在列表中时,列表才会重新组合。

当搜索栏在应用程序栏中时,如何使其工作?

谢谢你,

编辑:通过在初始化ViewModel时生成一个随机值,Hilt似乎在Searchbar可组合和项目可组合中注入了两个不同的实例。

是否可以将ViewModel作为单例注入?或者我应该将数据保存在存储库中,然后将这些数据提供给ViewModel?

下面是不同类的代码:

Searchbar.kt

@Composable
fun SearchBar(itemViewModel: ItemViewModel = hiltViewModel()){
var searchText by remember { mutableStateOf("") }

    BasicTextField(
        singleLine = true,
        cursorBrush = SolidColor(Color.White),
        value = searchText,
        onValueChange = {
            searchText = it
            itemViewModel.searchByLabel(it)
        },
        modifier = Modifier
            .fillMaxWidth()
            .height(28.dp),
        textStyle = LocalTextStyle.current.copy(
            color = Color.White,
            fontSize = MaterialTheme.typography.body2.fontSize
        ),
        decorationBox = { innerTextField ->
            Row(
                verticalAlignment = Alignment.CenterVertically,
                horizontalArrangement = Arrangement.spacedBy(4.dp)
            ) {
                Icon(
                    Icons.Filled.Search,
                    contentDescription = "Search"
                )
                Column(Modifier.weight(1f)) {
                    Box(
                        modifier = Modifier.fillMaxWidth()
                    ) {
                        if (searchText.isEmpty()) {
                            Text(
                                "Search",
                                style = LocalTextStyle.current.copy(
                                    color = Color.White.copy(alpha = 0.7f),
                                    fontSize = MaterialTheme.typography.body2.fontSize
                                )
                            )
                        }
                        innerTextField()
                    }
                }
                if (searchText.isNotEmpty()) {
                    IconButton(onClick = { searchText = "" }) {
                        Icon(Icons.Filled.Cancel, contentDescription = "Delete")
                    }
                }
            }
        }
    )
}

项目.kt

@Composable
fun Items(
    navController: NavController,
    itemViewModel: ItemViewModel = hiltViewModel(),
){
    val items = itemViewModel.items
    items?.let { items ->
        LazyColumn(
            modifier = Modifier.fillMaxWidth(),
            verticalArrangement = Arrangement.spacedBy(24.dp)
        ) {
    
            items(items) { item ->
                Row(
                    modifier = Modifier
                        .fillMaxWidth()
                        .clickable {
                            navController.navigate("items/${item.id}")
                        },
                    Arrangement.spacedBy(8.dp)
                ) {
                    Text(item.label)
                }
            }
        }
    } ?: run {
        Text(
            text = "No protocols",
            modifier = Modifier.fillMaxWidth()
        )
    }
}

ItemViewModel.kt

@HiltViewModel
class ItemViewModel @Inject constructor(private val repository: ItemRepository) : ViewModel() {
     var items by mutableStateOf<List<Item>?>(null)

     init{ loadItems() }

     private fun loadItems(){
         viewModelScope.launch {
             items = repository.getItems()
         }
     }

     fun searchByLabel(value: String){
         viewModelScope.launch {
             items = repository.search(value)
         }
     }
}

ItemRepository.kt

class ItemRepository(){
    suspend fun getItems(): List<Item>? {
        return listOf(Item(1, "Label 1"), Item(2, "Label 2"), Item(3, "Label 3"))
    }

    suspend fun search(value: String): List<Item>? {
        return getItems()?.filter { it.label.lowercase().contains(value.lowercase())}
    }
}

Item.kt

data class Item(var id: Int, var label: String){}

共有1个答案

彭兴朝
2023-03-14

我最终将数据存储在存储库中,该存储库作为单例注入。这样,即使创建了ViewModel的多个实例,它们仍然访问相同的数据

 类似资料:
  • 在R中是否有一种方法可以对数据帧中的每个不同变量使用不同的组合运行GLM。 如果我有4个解释变量,我可以将Y建模为

  • 我正试图创建一个产品清单使用谷歌表。每种类型的产品都有许多属性(或变体),这些属性组合在一起可以创建单个产品。 例如,有 直径:1/4英寸、1/2英寸、3/4英寸等。 长度:1/2英寸、1英寸、1/2英寸等 材料:钢、不锈钢 等等 特定产品是这些变化的特定组合。例如: 1/4英寸X 1/2英寸钢制圆头方颈螺栓 我要做的是创建一系列只包含属性的列。因此,直径柱、长度柱、材料柱等。 然后,我想通过将这

  • 我有亲戚 并想在PostgreSQL中加入它 所以我得到了所有可能的替换组合(即替换或多或少的笛卡尔积)。所以组1没有更新,组2只有B2,组3只有D2,组4都有B2和D2。 结尾应该是这样的,但应该对更多人开放(就像D1的额外D3) 编辑: 另一个可能的替换表可以是 可能会导致6组(我希望我没有忘记一个案例) 如果你有三个替代品,比如 这将导致8组。到目前为止,我所尝试的并没有真正的帮助: 我很高

  • 使用组件的目的就是通过构建模块化的组件,相互组合组件最后组装成一个复杂的应用。 在 React 组件中要包含其他组件作为子组件,只需要把组件当作一个 DOM 元素引入就可以了。 一个例子:一个显示用户头像的组件 Avatar 包含两个子组件 ProfilePic 显示用户头像和 ProfileLink 显示用户链接: import React from 'react'; import { rend

  • 几个小时寻找答案后,我终于放弃了。我有一个包含以下组合框的FXML表单: 它注入到 JavaFX 控制器类中: 该组合显示了使用Eclipselink 2.7和JPA 2.2从嵌入式H2数据库加载的Tobra(在西班牙语中代表Tipo de Obra)列表。 我不会向用户展示Tobra的价值。toString,相反,我在初始化中设置了一个转换器: 我有一个实现<code>Task的内部类 当然,当

  • 问题内容: 我尝试使用创建在一个列中具有两个值的视图,并且该视图已成功创建,但是当我尝试从中选择所有视图时,出现此错误: 我尝试研究此操作和串联运算符,但令我沮丧的是没有找到任何帮助。这是我用来创建视图和选择的代码。 问题答案: Oracle中的串联运算符是双管道。所述用于添加数字加在一起,因此,该错误。 该视图已成功创建,因为Oracle在创建数据时不会评估数据;仅确保它可以编译。