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

LiveData二次API调用未更新值问题排查与解决求助

解决按钮点击更新LiveData无效的问题

你遇到的问题根源有两个:

  • 每次点击按钮调用fetchCurrencyRates()时,都会重新创建ViewModel、Repository实例,导致你观察的是全新的LiveData对象,之前旧实例的更新根本没被当前观察者监听。
  • ViewModel中没有提供触发重新获取数据的方法,点击按钮时无法主动触发API请求刷新数据。

1. 修改ViewModel,添加刷新方法

给ViewModel新增公开方法,用于触发重新获取汇率数据,同时保持LiveData的引用不变:

class MainViewModel(private val repository: CurrencyRepository) : ViewModel() {

    init {
        // 初始化时首次加载数据
        refreshCurrencyRates()
    }

    // 对外暴露的刷新方法
    fun refreshCurrencyRates() {
        viewModelScope.launch {
            repository.getCurrencyExchangeList()
        }
    }

    val quotes: LiveData<CurrencyData>
        get() = repository.currencyLiveData
}

2. 重构Activity代码,复用ViewModel

把ViewModel的初始化移到onCreate()方法中,确保整个Activity生命周期内只使用同一个ViewModel实例;点击按钮时直接调用ViewModel的刷新方法:

class MainActivity : AppCompatActivity() {
    private lateinit var mainViewModel: MainViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // 仅初始化一次ViewModel
        val currencyService = RetrofitHelper.getInstance().create(CurrencyInterface::class.java)
        val repository = CurrencyRepository(currencyService)
        mainViewModel = ViewModelProvider(this, MainViewModelFactory(repository))[MainViewModel::class.java]

        // 仅设置一次观察者,后续LiveData更新会自动回调
        mainViewModel.quotes.observe(this) {
            Log.d("AllCurrencyList", it.updated)
            // 这里添加UI更新逻辑,比如刷新汇率列表
        }

        // 绑定按钮点击事件
        findViewById<Button>(R.id.refresh_btn).setOnClickListener {
            mainViewModel.refreshCurrencyRates()
        }
    }
}

3. 优化Repository(可选)

Retrofit的suspend方法默认在IO线程执行,建议用postValue()安全更新LiveData(value仅能在主线程调用):

class CurrencyRepository(private val currencyService: CurrencyInterface) {

    val currencyLiveData = MutableLiveData<CurrencyData>()

    suspend fun getCurrencyExchangeList() {
        val result = currencyService.getAllCurrencyData()
        result.body()?.let {
            // 子线程中用postValue更新LiveData
            currencyLiveData.postValue(it)
        }
    }
}

关键修改说明

  • 复用ViewModel:ViewModel生命周期与Activity绑定,仅初始化一次才能保证观察者监听的是同一个LiveData对象,后续更新才能被正常接收。
  • 主动触发刷新:通过ViewModel暴露的refreshCurrencyRates()方法,点击按钮时主动发起API请求,让Repository更新LiveData的值。
  • 线程安全更新:用postValue()避免在IO线程直接调用value导致的主线程检查异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 18:43:22