如何从Manufacturers模块获取数据填充ExposedDropdownMenu?
1. Room 实体与DAO定义
先确保你的Room实体和DAO包含必要的核心方法:
厂商实体
@Entity(tableName = "manufacturers") data class Manufacturer( @PrimaryKey(autoGenerate = true) val id: Int = 0, val name: String )
产品实体(关联厂商ID)
@Entity( tableName = "products", foreignKeys = [ForeignKey( entity = Manufacturer::class, parentColumns = ["id"], childColumns = ["manufacturer_id"], onDelete = ForeignKey.CASCADE )] ) data class Product( @PrimaryKey(autoGenerate = true) val id: Int = 0, val name: String, val price: Double, @ColumnInfo(name = "manufacturer_id") val manufacturerId: Int )
DAO 接口
@Dao interface AppDao { // 获取所有厂商的Flow,实时监听数据变化 @Query("SELECT * FROM manufacturers ORDER BY name ASC") fun getAllManufacturers(): Flow<List<Manufacturer>> // 插入新产品 @Insert suspend fun insertProduct(product: Product) }
2. Repository 层
封装数据操作,统一暴露给ViewModel:
class AppRepository(private val dao: AppDao) { val allManufacturers: Flow<List<Manufacturer>> = dao.getAllManufacturers() suspend fun insertProduct(product: Product) { dao.insertProduct(product) } }
3. ViewModel 层
管理UI状态,处理厂商列表和选中逻辑:
class AddProductViewModel(private val repository: AppRepository) : ViewModel() { // 将厂商Flow转为StateFlow,供Compose观察 val manufacturers = repository.allManufacturers .stateIn( viewModelScope, SharingStarted.WhileSubscribed(5000), emptyList() ) // 选中的厂商状态 private val _selectedManufacturer = mutableStateOf<Manufacturer?>(null) val selectedManufacturer = _selectedManufacturer.asState() // 更新选中的厂商 fun onManufacturerSelected(manufacturer: Manufacturer) { _selectedManufacturer.value = manufacturer } // 提交新产品 suspend fun submitProduct(productName: String, price: Double) { selectedManufacturer.value?.let { manufacturer -> val product = Product( name = productName, price = price, manufacturerId = manufacturer.id ) repository.insertProduct(product) } } }
4. Compose UI 实现(ExposedDropdownMenu)
构建添加产品界面,集成厂商选择下拉菜单:
@Composable fun AddProductScreen(viewModel: AddProductViewModel = hiltViewModel()) { val manufacturers by viewModel.manufacturers.collectAsState() val selectedManufacturer by viewModel.selectedManufacturer val (productName, onProductNameChange) = remember { mutableStateOf("") } val (priceText, onPriceTextChange) = remember { mutableStateOf("") } val price = priceText.toDoubleOrNull() ?: 0.0 // 下拉菜单展开状态 val (expanded, setExpanded) = remember { mutableStateOf(false) } Scaffold(topBar = { TopAppBar(title = { Text("添加新产品") }) }) { padding -> Column( modifier = Modifier .fillMaxSize() .padding(padding) .padding(16.dp), verticalArrangement = Arrangement.spacedBy(16.dp) ) { // 产品名称输入框 OutlinedTextField( value = productName, onValueChange = onProductNameChange, label = { Text("产品名称") }, modifier = Modifier.fillMaxWidth() ) // 价格输入框 OutlinedTextField( value = priceText, onValueChange = onPriceTextChange, label = { Text("产品价格") }, keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number), modifier = Modifier.fillMaxWidth() ) // 厂商选择下拉菜单 ExposedDropdownMenuBox( expanded = expanded, onExpandedChange = { setExpanded(!expanded) } ) { OutlinedTextField( readOnly = true, value = selectedManufacturer?.name ?: "选择厂商", onValueChange = {}, label = { Text("厂商") }, trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = expanded) }, modifier = Modifier .fillMaxWidth() .menuAnchor() ) ExposedDropdownMenu( expanded = expanded, onDismissRequest = { setExpanded(false) } ) { if (manufacturers.isEmpty()) { DropdownMenuItem( text = { Text("暂无厂商数据") }, onClick = { setExpanded(false) }, enabled = false ) } else { manufacturers.forEach { manufacturer -> DropdownMenuItem( text = { Text(manufacturer.name) }, onClick = { viewModel.onManufacturerSelected(manufacturer) setExpanded(false) } ) } } } } // 提交按钮 Button( onClick = { viewModelScope.launch { viewModel.submitProduct(productName, price) // 提交成功后可清空输入或返回上一页 } }, enabled = productName.isNotBlank() && price > 0 && selectedManufacturer != null, modifier = Modifier.fillMaxWidth() ) { Text("添加产品") } } } }
额外提示
- 建议用Hilt或其他依赖注入框架管理ViewModel和Repository实例,避免生命周期问题
- 可补充输入校验逻辑,比如价格格式错误、未选择厂商时的Toast提示
- 若需要支持厂商搜索,可在ExposedDropdownMenu上方添加搜索输入框,过滤厂商列表
内容的提问来源于stack exchange,提问作者Franklin
相关产品推荐
相关产品推荐

