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

Android MVVM下RxJava调用Spoonacular API次数翻倍问题求助

问题根因

1. LiveData观察者重复注册(核心原因)

你将dishViewModelObserver()观察者注册方法放到了每次点击按钮都会触发的apiCall()方法中,每次点击都会为3个LiveData实例各新增一个观察者。LiveData触发回调时,所有已经注册过的观察者都会同时执行,点击N次就会返回N次结果,看起来就像API被调用了多次、返回了多条数据。

2. 辅助问题:RxJava订阅未及时释放

ViewModel中的CompositeDisposable没有在ViewModel销毁时执行释放逻辑,存在内存泄漏风险,极端场景下也可能导致订阅重复执行。

修复方案
  1. 调整观察者注册时机,仅在页面初始化时注册一次
    修改SearchFragment代码,将观察者注册逻辑移到onViewCreated中,apiCall方法仅保留触发接口请求的逻辑:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    mDishApiViewModel= ViewModelProvider(this)[DishApiViewModel::class.java]
    // 仅页面初始化时注册一次观察者
    dishViewModelObserver()

    mBinding!!.btn.setOnClickListener{
        if(mBinding!!.et.text.isEmpty()){
            Toast.makeText(requireContext(), "Please enter dish type", Toast.LENGTH_SHORT).show()
        }else{
            apiCall(mBinding!!.et.text.toString())
        }
    }
}

private fun apiCall(filter:String){
    // 移除这里的观察者注册逻辑,仅触发接口请求
    mDishApiViewModel.getRecipesFromAPI(filter)
}
  1. 为ViewModel添加订阅释放逻辑,避免内存泄漏
    在DishApiViewModel中重写onCleared方法:
override fun onCleared() {
    super.onCleared()
    // 页面销毁时释放所有RxJava订阅
    compositeDisposable.dispose()
}
  1. 可选优化:每次发起新请求前清理旧订阅
    如果需要避免前一次请求未完成时,用户重复点击发起重复请求,可以在getRecipesFromAPI方法开头添加清理逻辑:
fun getRecipesFromAPI(filter:String){
    // 先清理之前未完成的订阅
    compositeDisposable.clear()
    loadDish.value=true
    // 原有逻辑保持不变
    ...
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 16:24:09