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

如何在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:58:26