向Room数据库插入数据后LiveData未更新问题排查
我帮你排查了代码细节,找到了几个导致LiveData更新后界面无反应的关键问题:
1. Adapter未通知RecyclerView数据变化
你的ProductAdapter里的setProducts方法仅仅完成了mProducts的赋值,但没有触发RecyclerView的刷新逻辑。Room的LiveData确实会在数据库发生变化时推送新的产品列表,但Adapter不知道数据已经更新,自然不会刷新界面。
修改setProducts方法,添加刷新通知:
fun setProducts(products : List<Product>) { this.mProducts = products notifyDataSetChanged() // 新增该行,通知RecyclerView更新UI }
如果追求更高效的局部刷新,后续可以改用DiffUtil实现,但先添加notifyDataSetChanged()就能快速解决当前问题。
2. 主线程执行同步查询的潜在风险
你的Repository里的isProductAlreadyAdded方法直接调用了DAO的同步查询getProductAddedToCertainList,而Room默认禁止在主线程执行非LiveData类型的查询(除非你在数据库构建时开启了allowMainThreadQueries())。这虽然不是当前LiveData不更新的直接原因,但可能导致NetworkOnMainThreadException或者ANR,需要提前修复。
推荐用Coroutines改造异步查询:
首先在Repository中添加Coroutines支持:
private val scope = CoroutineScope(Dispatchers.IO) fun insertProductInProductList(productCode : String) : Boolean { var isAlreadyAdded = false runBlocking { isAlreadyAdded = isProductAlreadyAdded(productCode) if(!isAlreadyAdded) { productsInProductListDao.insertProductInProductList(ProductsInProductList(listName, productCode)) } } return !isAlreadyAdded } private suspend fun isProductAlreadyAdded(productCode : String): Boolean { return withContext(Dispatchers.IO) { productsInProductListDao.getProductAddedToCertainList(listName, productCode).isNotEmpty() } }
同时给DAO的对应方法加上suspend关键字:
@Query("SELECT code, model, pvpr, qtr, segmentation FROM product_table INNER JOIN products_in_productlist_table ON code=productCode WHERE listName=:listName and code=:productCode") suspend fun getProductAddedToCertainList(listName : String, productCode: String) : List<Product>
3. DAO方法的拼写错误(疑似笔误)
你的DAO里的方法名getProducstForProductList存在拼写错误(Producst应为Products),如果这是实际代码中的错误,会导致查询无法正确执行,进而让LiveData无法获取更新后的数据。请检查并修正这个拼写问题。
总结
最直接导致界面不更新的原因是Adapter缺少刷新通知,先修复这个问题,应该就能看到列表正常更新了。之后再逐步修复主线程查询的问题,避免后续出现崩溃风险。
内容的提问来源于stack exchange,提问作者Sergio Santano

