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

MutableLiveData首次触发后不再更新UI问题排查

问题解决:分类切换后UI不更新的问题

问题分析

启动Activity时子分类和产品能正常加载,但切换其他分类时,API返回数据正确,但UI无变化。核心原因是ViewModel中的LiveData被重新赋值,导致Fragment观察的旧实例无法接收新数据。

查看ViewModel代码:每次调用getSubcategoryAndProducts时,都会重新创建一个MutableLiveData并赋值给subCategoryAndProductsResult,但Fragment在onViewCreated中观察的是初始化时的LiveData实例,新实例的变化不会被监听,自然无法触发UI更新。

修复步骤

1. 修改ViewModel代码

不要重新创建LiveData实例,复用已有的实例并更新其值:

var subCategoryAndProductsResult = MutableLiveData<ResultData>()

fun getSubcategoryAndProducts(categoryId: Int) {
    Log.d("calling api", "Calling products Api")

    categoriesDataSource.getSubcategoryAndProducts(categoryId, 0, 0)
        .observeForever(object : Observer<ResultData> {
            override fun onChanged(result: ResultData) {
                subCategoryAndProductsResult.value = result
                // 移除观察者,避免内存泄漏
                categoriesDataSource.getSubcategoryAndProducts(categoryId, 0, 0).removeObserver(this)
            }
        })
}

2. 优化DataSource代码(可选,更简洁)

让DataSource直接更新ViewModel的LiveData,避免返回新实例:

fun getSubcategoryAndProducts(
    categoryId: Int,
    userId: Int,
    storeId: Int,
    liveData: MutableLiveData<ResultData>
) {
    val categoriesAndProductsApis = retrofitClient.createService(CategoriesAndProductsApis::class.java)
    val response = categoriesAndProductsApis.getSubcategoryAndProducts(categoryId, userId, storeId)

    response.enqueue(object : Callback<ApiResponse> {
        override fun onResponse(call: Call<ApiResponse>, response: Response<ApiResponse>) {
            Log.d("Products ", response.code().toString())
            if (response.isSuccessful) {
                val body = response.body()
                if (body != null && body.statusCode == 200) {
                    val result = ResultData(body.data!!, "")
                    liveData.setValue(result)
                    Log.v("Products", result.success.toString())
                } else {
                    val result = ResultData("", "Something went wrong")
                    liveData.postValue(result)
                    Log.v("result", result.error.toString())
                }
            }
        }

        override fun onFailure(call: Call<ApiResponse>, t: Throwable) {
            val result = ResultData("", "Something went wrong")
            liveData.setValue(result)
            Log.v("result", result.error.toString())
        }
    })
}

对应ViewModel调用逻辑修改为:

fun getSubcategoryAndProducts(categoryId: Int) {
    Log.d("calling api", "Calling products Api")
    categoriesDataSource.getSubcategoryAndProducts(categoryId, 0, 0, subCategoryAndProductsResult)
}

3. 确认Fragment与适配器逻辑

  • 确保Fragment中addSubcategoryAndProducts()方法正确更新了适配器的数据源
  • 适配器中notifyDataSetChanged()需在数据源更新后调用(当前代码逻辑已满足,但需确保数据确实被替换)

关键注意点

  • LiveData实例必须保持唯一,观察者才能持续接收数据变化
  • 避免每次请求时重新创建LiveData,应复用已有实例更新值
  • 使用临时观察者时,需及时移除防止内存泄漏

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 00:06:13