Kotlin Jetpack Compose中如何向ViewModel传递查询参数
问题描述
我是Kotlin新手,正在使用Jetpack Compose开发应用,遇到参数传递的问题:
DAO中编写的查询语句:
@Query("SELECT * FROM GrungeInfoDbModel WHERE infoname = :infoname") fun getInfoGrunge(infoname: String): GrungeInfoDbModel
Repository接口声明:
interface Repository { fun getAllGrunges(): LiveData<List<GrungeModel>> fun getAllGrungeInfos(): LiveData<List<GrungeInfoModel>> fun getGrungeInfo(infoname: String): LiveData<GrungeInfoModel> }
RepositoryImpl已实现getGrungeInfo方法并返回对应的LiveData。当前核心问题:如何将infoname参数传递到ViewModel的这段代码中:
val grungeInfoByInfoname by lazy { repository.getGrungeInfo(**此处需传入infoname参数) }
解决方案
这里的核心矛盾是lazy初始化逻辑仅在首次访问时执行一次,无法动态接收参数。可以通过以下几种方式解决:
方法1:用StateFlow实现动态参数响应
在ViewModel中用MutableStateFlow存储当前要查询的infoname,通过流转换自动更新查询结果:
class YourViewModel(private val repository: Repository) : ViewModel() { // 存储当前查询的infoname,可设置合适的初始值 private val _currentInfoname = MutableStateFlow("") val currentInfoname = _currentInfoname.asStateFlow() // 动态生成对应infoname的查询结果LiveData val grungeInfoByInfoname: LiveData<GrungeInfoModel> = currentInfoname .map { infoname -> if (infoname.isNotBlank()) repository.getGrungeInfo(infoname) else null } .flatMapLatest { it ?: MutableLiveData() } .asLiveData(viewModelScope.coroutineContext) // 对外暴露更新infoname的方法 fun updateInfoname(newInfoname: String) { _currentInfoname.value = newInfoname } }
使用时,调用updateInfoname传入目标参数,grungeInfoByInfoname会自动同步为对应的查询结果。
方法2:将infoname作为ViewModel构造参数传入
如果查询的infoname在ViewModel初始化时就确定(比如进入页面时已知),可以直接将其作为构造参数传入:
class YourViewModel( private val repository: Repository, private val infoname: String ) : ViewModel() { val grungeInfoByInfoname by lazy { repository.getGrungeInfo(infoname) } }
需要通过ViewModel工厂类传递参数,示例如下:
class YourViewModelFactory( private val repository: Repository, private val infoname: String ) : ViewModelProvider.Factory { override fun <T : ViewModel> create(modelClass: Class<T>): T { if (modelClass.isAssignableFrom(YourViewModel::class.java)) { @Suppress("UNCHECKED_CAST") return YourViewModel(repository, infoname) as T } throw IllegalArgumentException("未知ViewModel类") } } // 在Compose中创建ViewModel val targetInfoname = "目标参数值" val viewModel: YourViewModel = viewModel(factory = YourViewModelFactory(repository, targetInfoname))
方法3:直接调用方法获取结果(无缓存)
如果不需要缓存LiveData实例,每次查询时直接调用Repository方法即可:
class YourViewModel(private val repository: Repository) : ViewModel() { fun getGrungeInfoByInfoname(infoname: String): LiveData<GrungeInfoModel> { return repository.getGrungeInfo(infoname) } }
在Compose中使用时,直接调用方法并收集结果:
val targetInfoname = "目标参数值" val viewModel = viewModel<YourViewModel>() val grungeInfo by viewModel.getGrungeInfoByInfoname(targetInfoname).observeAsState(null)
额外注意
DAO方法返回的是GrungeInfoDbModel,但Repository返回的是LiveData<GrungeInfoModel>,请确保在RepositoryImpl中已完成数据库模型到UI模型的转换,避免类型不匹配问题。
内容的提问来源于stack exchange,提问作者Erdem
相关产品推荐
相关产品推荐

