为什么我的Kotlin函数返回kotlin.Unit而非布尔值?Room注册校验问题
问题根因
你遇到的问题核心有两点:
CustomerViewModel的addCustomer方法未定义返回值,默认返回Unit类型,你将Unit赋值给flag和true做比较,结果永远为假,所以只会走else分支。- 你用
viewModelScope.launch启动了异步协程执行数据库操作,协程内部的返回值无法直接透传给外部同步调用的代码,你拿到的flag永远是方法本身的返回值Unit,和协程执行结果无关。
另外你当前的校验逻辑只能捕获数据库写入异常,无法主动识别用户名/邮箱重复,需要额外补充校验逻辑。
修复步骤
步骤1:给数据库表加唯一约束
先给Customer实体类的userName和email字段加唯一索引,从数据库层面避免重复数据写入:
@Entity( tableName = "customers", indices = [Index(value = ["userName", "email"], unique = true)] ) class Customer( // 原有字段不变 ... )
步骤2:新增重复校验的DAO方法
在CustomerDao中增加查询方法,判断是否存在相同的用户名或邮箱:
@Query("SELECT COUNT(*) FROM customers WHERE userName = :userName OR email = :email") suspend fun checkDuplicate(userName: String, email: String): Int
步骤3:改造Repository层逻辑
将addCustomer改为suspend方法,先做重复校验再执行写入:
suspend fun addCustomer(customer: Customer): Boolean { return try { // 先校验是否存在重复数据 val duplicateCount = customerDao.checkDuplicate(customer.userName, customer.email) if (duplicateCount > 0) { // 存在重复直接返回false return false } customerDao.addCustomers(customer) true } catch (ex: Exception) { // 写入异常返回false false } }
步骤4:改造ViewModel层逻辑
这里提供两种改造方案,二选一即可:
方案A:将ViewModel方法改为suspend方法(推荐)
suspend fun addCustomer(customer: Customer): Boolean { // 切到IO线程执行数据库操作 return withContext(Dispatchers.IO) { repository.addCustomer(customer) } }
调用层代码改为在生命周期协程中调用:
val customer = Customer(0, firstName, lastName, userName, password, address, city, postalCode, email, phone) // 页面层用lifecycleScope启动协程调用 lifecycleScope.launch { val flag = mCustomerViewModel.addCustomer(customer) println("FLAG ---> $flag") if (flag) { Toast.makeText(applicationContext, "Success", Toast.LENGTH_SHORT).show() } else { Toast.makeText(applicationContext, "用户名或邮箱已存在", Toast.LENGTH_SHORT).show() } }
方案B:用LiveData回传执行结果
// 定义结果回调的LiveData val addCustomerResult = MutableLiveData<Boolean>() fun addCustomer(customer: Customer) { viewModelScope.launch(Dispatchers.IO) { val result = repository.addCustomer(customer) // 切主线程更新LiveData addCustomerResult.postValue(result) } }
调用层先观察LiveData再触发添加操作:
// 先观察添加结果 mCustomerViewModel.addCustomerResult.observe(this) { flag -> if (flag) { Toast.makeText(applicationContext, "Success", Toast.LENGTH_SHORT).show() } else { Toast.makeText(applicationContext, "用户名或邮箱已存在", Toast.LENGTH_SHORT).show() } } // 触发添加操作 val customer = Customer(0, firstName, lastName, userName, password, address, city, postalCode, email, phone) mCustomerViewModel.addCustomer(customer)
内容的提问来源于stack exchange,提问作者user17312483
相关产品推荐
相关产品推荐

