You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android ViewModel中如何将insertUser返回的id传递给insertMoney函数

问题原因

  1. 异步执行时序问题:insertUser 内部通过uiScope.launch启动了异步协程任务,数据库插入逻辑是在IO线程执行的耗时操作。你在Fragment中调用insertUser后立刻执行insertMoney,此时insertUser的数据库插入操作还未完成,全局变量idT还没被赋值,因此拿到的是空字符串。
  2. 全局变量设计缺陷:用全局变量idT存储单次操作的临时id本身就不合理,多并发场景下极易出现脏读、值被覆盖的问题,完全不适合该场景的参数传递需求。

解决方案

最直接的优化方式是调整函数结构,将insertUser改为可返回插入id的挂起函数,在调用侧按顺序执行两个操作,完全不需要额外定义全局变量存储中间值:

第一步 修改ViewModel代码

// 删掉原有全局变量idT
class AddUserViewModel(
    val mUserInfoDAO: UserDAO,
    val mTransactionDAO: TransactionsDAO,
    val mLoan: LoanDAO,
    val mBankDAO: BankDAO,
    application: Application
) : AndroidViewModel(application) {
    var viewModelJob = Job()
    val uiScope = CoroutineScope(Dispatchers.Main + viewModelJob)

    // 改为挂起函数,执行完成直接返回插入的用户id
    suspend fun insertUser(
        fullName: String,
        accountId: String,
        mobileNumber: String,
        phoneNumber: String,
        dateOfCreation: String,
        address: String,
    ): Long = withContext(Dispatchers.IO) {
        return@withContext try {
            Log.d("TAG", "insertTest")
            val user = UserInfo(
                0L,
                fullName,
                accountId,
                mobileNumber,
                phoneNumber,
                dateOfCreation,
                address
            )
            val id = mUserInfoDAO.insert(user)
            Log.d("TAG", "insertUser: $id")
            id
        } catch (e: Exception) {
            Log.d("TAG", "insertContact: ${e.message}")
            -1L // 异常场景返回无效id供调用侧判断
        }
    }

    // 新增userId参数接收插入的用户id
    fun insertMoney(
        amount: String,
        increasePage: String?,
        userId: Long
    ) {
        Log.d("TAG", "insertUserTTT: $userId")
        val bankId: Long = bankInfo.value?.get(selectedItemPosition)?.bankId!!
        uiScope.launch {
            mTransactionDAO.insert(
                Transaction(
                    0L,
                    userId, // 直接使用传入的id
                    null,
                    bankId,
                    null,
                    amount,
                    null,
                    null,
                    null,
                    increasePage
                )
            )
        }
    }

    // 新增onCleared逻辑防止内存泄漏
    override fun onCleared() {
        super.onCleared()
        viewModelJob.cancel()
    }
}

第二步 修改Fragment调用逻辑

mAddUserViewModel.addUser.observe(viewLifecycleOwner, Observer {
    if (it == true) {
        // 启动生命周期协程按顺序执行操作
        lifecycleScope.launch {
            val userId = mAddUserViewModel.insertUser(
                mAddUserListBinding.fullName.text.toString(),
                mAddUserListBinding.accountId.text.toString(),
                mAddUserListBinding.mobileNumber.text.toString(),
                mAddUserListBinding.phoneNumber.text.toString(),
                mAddUserListBinding.createdDate.text.toString(),
                mAddUserListBinding.edtAddress.text.toString(),
            )
            // 仅插入用户成功后再执行插入金额逻辑
            if (userId != -1L) {
                val firstMoney = "firstMoney"
                mAddUserViewModel.insertMoney(
                    mAddUserListBinding.firstMoney.text.toString(),
                    firstMoney,
                    userId
                )
            }
            findNavController().popBackStack()
        }
    }
})

内容的提问来源于stack exchange,提问作者AmirHossein

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 03:45:03