如何在ViewModel中实现SQLite数据变更后获取最新数据?
问题分析与修复方案
这个问题的核心原因很明确:你的FavoriteViewModel里的favoriteEventList只在ViewModel初始化时加载了一次数据库数据,执行删除操作后没有重新查询数据库并更新LiveData的值,所以Fragment观察的LiveData始终持有旧数据,只有重新创建Fragment时才会重新触发数据加载。
修复步骤与代码调整
1. 重构FavoriteViewModel,让LiveData可以被更新
我们需要复用同一个MutableLiveData实例,并且在删除操作完成后主动重新加载数据并更新它的值:
class FavoriteViewModel(application: Application) : AndroidViewModel(application) { // 初始化一个空的MutableLiveData,后续复用这个实例更新数据 private val favoriteEventList = MutableLiveData<MutableList<Favorite>>() init { // 初始化时加载数据 loadFavoriteEvents(application) } fun getFavorite(): LiveData<MutableList<Favorite>> = favoriteEventList // 修改为更新已有LiveData的方法,不再返回新的实例 private fun loadFavoriteEvents(context: Context) { val favorites: MutableList<Favorite> = mutableListOf() context.database.use { val result = select(Favorite.TABLE_FAVORITE) val favorite = result.parseList(classParser<Favorite>()) favorites.addAll(favorite) // 更新LiveData的值,触发观察者回调 favoriteEventList.postValue(favorites) } } fun removeFromFavorite(context: Context, param: String) { try { context.database.use { delete( Favorite.TABLE_FAVORITE, "(${Favorite.EVENT_ID} = {id})", "id" to param ) } showToast(context, "Removed from favorite") // 删除完成后,重新加载数据并更新LiveData loadFavoriteEvents(context) } catch (e: SQLiteConstraintException) { showToast(context, "Error : ${e.localizedMessage}") } } }
2. 优化FavoriteFragment的ViewModel使用
建议把ViewModel的获取移到onViewCreated中,避免每次onResume重复获取(虽然ViewModelProviders.of(this)会返回同一个实例,但这样更规范),同时保持观察逻辑:
private lateinit var favoriteViewModel: FavoriteViewModel override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) favoriteViewModel = ViewModelProviders.of(this)[FavoriteViewModel::class.java] // 只需要观察一次,LiveData更新时会自动回调 favoriteViewModel.getFavorite().observe(viewLifecycleOwner, Observer { progressBar.gone() favoriteList.clear() favoriteList.addAll(it) }) } override fun onResume() { super.onResume() // 如果需要每次回到页面都强制刷新数据,可以在这里调用加载方法 // favoriteViewModel.loadFavoriteEvents(requireContext()) }
关键修改点说明
- 复用MutableLiveData实例:原来的代码每次调用
getFavoriteEvent都会创建新的MutableLiveData,Fragment观察的是旧的实例,自然接收不到更新。现在我们始终使用同一个实例,更新它的值就能触发观察者的回调。 - 删除后主动加载数据:在
removeFromFavorite方法执行完删除操作后,调用loadFavoriteEvents重新查询数据库并更新LiveData,这样Fragment就能立即收到最新数据。 - 使用
postValue:如果数据库操作涉及子线程(虽然Anko的use默认在主线程,但保险起见),postValue可以确保在主线程更新LiveData的值,避免线程安全问题。
这样修改后,删除数据后Fragment会自动刷新显示最新的收藏列表,不需要重新打开页面了。
内容的提问来源于stack exchange,提问作者Afdal
相关产品推荐
相关产品推荐

