如何在添加记录时将主键ID传入另一条记录?Kotlin Flow场景
解决Kotlin Flow异步创建Account后无法获取accountId创建Transaction的问题
问题分析
- 点击事件中
addAccount是异步协程操作,更新account变量的逻辑在IO线程的collect块中,后续直接获取accountVM.account.accountId时,变量还未完成更新,导致传入空/无效的id。 getLatestAccount方法仅调用了仓库查询逻辑,但未将结果赋值给account变量,完全起不到更新作用。
解决方案
核心思路是等待Account创建完成并拿到带生成id的实体后,再执行Transaction的创建,以下两种方式均可实现:
方式一:将addAccount改为挂起函数直接返回创建后的Account
1. 修改AccountViewModel
var account by mutableStateOf(Account("")) // 改为挂起函数,返回插入后带accountId的Account实例 suspend fun addAccount(account: Account): Account { val createdAccount = repository.addAccountRepo(account).first() this.account = createdAccount // 同步更新UI状态 return createdAccount }
2. 修改UI层点击事件
在点击事件中启动协程,等待addAccount返回结果后再调用addTransaction:
// Compose示例:在按钮点击事件中启动协程 Button(onClick = { lifecycleScope.launch { // 或根据上下文使用viewModelScope val createdAccount = accountVM.addAccount(Account(accountName)) transactionVM.addTransaction(Transaction(createdAccount.accountId, trnxAmount)) } }) { Text("添加账户") }
方式二:让addAccount返回Flow,在UI层收集结果
1. 修改AccountViewModel
var account by mutableStateOf(Account("")) // 返回Flow,插入完成后emit带id的Account,并同步更新UI状态 fun addAccount(account: Account): Flow<Account> { return repository.addAccountRepo(account) .onEach { createdAccount -> this.account = createdAccount } .flowOn(Dispatchers.IO) }
2. 修改UI层点击事件
收集Flow获取创建后的Account实例,再执行Transaction创建:
Button(onClick = { lifecycleScope.launch { accountVM.addAccount(Account(accountName)).collect { createdAccount -> transactionVM.addTransaction(Transaction(createdAccount.accountId, trnxAmount)) } } }) { Text("添加账户") }
补充:确保Repository层正确返回带id的Account
假设使用Room数据库,DAO层需正确返回插入后的id或实体:
// DAO示例 @Dao interface AccountDao { // 方式一:返回插入的id,后续构造带id的Account @Insert suspend fun insertAccount(account: Account): Long // 方式二:直接返回带生成id的Account(Room 2.2+版本支持) @Insert(onConflict = OnConflictStrategy.REPLACE) suspend fun insertAccount(account: Account): Account } // Repository层实现 class AccountRepository(private val accountDao: AccountDao) { fun addAccountRepo(account: Account): Flow<Account> = flow { // 对应DAO方式一 val accountId = accountDao.insertAccount(account) emit(account.copy(accountId = accountId)) // 对应DAO方式二 // emit(accountDao.insertAccount(account)) }.flowOn(Dispatchers.IO) }
内容的提问来源于stack exchange,提问作者Danial
相关产品推荐
相关产品推荐

