Room查询列表为空,无法填充DropDownMenu问题求助
问题定位与修复方案
你的核心问题是ViewModel中从DAO获取的Bullet列表没有同步到UI依赖的AmmoState里,导致UI拿到的state.bulletName始终是初始空列表。另外还有几处细节需要完善,以下是分步修复:
1. 同步Bullet列表到AmmoState
ViewModel里单独的bulletName StateFlow没有和_state关联,UI自然拿不到数据。修改ViewModel,把DAO返回的Flow结果同步到AmmoState:
@OptIn(ExperimentalCoroutinesApi::class) class AmmoViewModel( private val dao: BBDao, ) : ViewModel() { private val _state = mutableStateOf(AmmoState()) val state = _state.asStateFlow() init { // 收集Bullet列表,更新到状态中 viewModelScope.launch { dao.getBulletNames().collect { bulletNames -> _state.update { it.copy(bulletName = bulletNames) } } } } fun onEvent(event: AmmoEvent) { when (event) { AmmoEvent.ShowDialog -> { _state.update { it.copy( isAddingAmmo = true, ammoBulletName = "", ) } } AmmoEvent.HideDialog -> { _state.update { it.copy(isAddingAmmo = false) } } is AmmoEvent.SetAmmoName -> { _state.update { it.copy(ammoName = event.name) } } is AmmoEvent.SetAmmoBulletName -> { _state.update { it.copy(ammoBulletName = event.bulletName) } } AmmoEvent.SaveAmmo -> { viewModelScope.launch { dao.insertAmmo( Ammo( ammoName = _state.value.ammoName, ammoBulletName = _state.value.ammoBulletName ) ) _state.update { it.copy(isAddingAmmo = false, ammoName = "") } } } } } }
2. 完善状态与事件定义
你的AmmoState和AmmoEvent缺少必要字段/事件类型,补充完整:
// 补充AmmoState缺失的字段 data class AmmoState( val bulletName: List<BulletNames> = emptyList(), val ammoName: String = "", val ammoBulletName: String = "", val isAddingAmmo: Boolean = false ) // 补充AmmoEvent缺失的事件 sealed interface AmmoEvent { data object ShowDialog : AmmoEvent data object HideDialog : AmmoEvent data object SaveAmmo : AmmoEvent data class SetAmmoName(val name: String) : AmmoEvent data class SetAmmoBulletName(val bulletName: String) : AmmoEvent }
3. 确认Bullet表存在数据
如果数据库里Bullet表本身是空的,查询结果当然为空。可以在数据库初始化时预插测试数据:
// 创建数据库时添加回调 val db = Room.databaseBuilder( context, BBDatabase::class.java, "bb_database" ).addCallback(object : RoomDatabase.Callback() { override fun onCreate(db: SupportSQLiteDatabase) { super.onCreate(db) // 预插测试Bullet数据 GlobalScope.launch { dao.insertBullet(Bullet("9mm")) dao.insertBullet(Bullet(".45 ACP")) } } }).build()
也可以用Android Studio的App Inspection直接查看数据库表内容。
4. 修复Dialog下拉菜单显示问题
Dialog里用item.toString()会显示BulletNames(bulletName=xxx),改成直接取字段值:
DropdownMenuItem( text = { Text(text = item.bulletName) }, onClick = { expanded = false selectedBullet = item.bulletName onEvent(AmmoEvent.SetAmmoBulletName(item.bulletName)) }, )
5. UI层正确接收状态
确保AmmoScreen观察ViewModel的StateFlow:
@Composable fun AmmoScreen( viewModel: AmmoViewModel = viewModel() ){ val state by viewModel.state.collectAsState() Scaffold ( floatingActionButton = { FloatingActionButton(onClick = { viewModel.onEvent(AmmoEvent.ShowDialog) }) { Icon(imageVector = Icons.Default.Add, contentDescription = "Add Ammo") } }, modifier = Modifier.padding(16.dp) ) {_ -> if(state.isAddingAmmo){ AddAmmoDialog(state = state, onEvent = viewModel::onEvent) } } }
内容的提问来源于stack exchange,提问作者Kurtis
相关产品推荐
相关产品推荐

