Android MVVM下RxJava调用Spoonacular API次数翻倍问题求助
问题根因
1. LiveData观察者重复注册(核心原因)
你将dishViewModelObserver()观察者注册方法放到了每次点击按钮都会触发的apiCall()方法中,每次点击都会为3个LiveData实例各新增一个观察者。LiveData触发回调时,所有已经注册过的观察者都会同时执行,点击N次就会返回N次结果,看起来就像API被调用了多次、返回了多条数据。
2. 辅助问题:RxJava订阅未及时释放
ViewModel中的CompositeDisposable没有在ViewModel销毁时执行释放逻辑,存在内存泄漏风险,极端场景下也可能导致订阅重复执行。
修复方案
- 调整观察者注册时机,仅在页面初始化时注册一次
修改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) }
- 为ViewModel添加订阅释放逻辑,避免内存泄漏
在DishApiViewModel中重写onCleared方法:
override fun onCleared() { super.onCleared() // 页面销毁时释放所有RxJava订阅 compositeDisposable.dispose() }
- 可选优化:每次发起新请求前清理旧订阅
如果需要避免前一次请求未完成时,用户重复点击发起重复请求,可以在getRecipesFromAPI方法开头添加清理逻辑:
fun getRecipesFromAPI(filter:String){ // 先清理之前未完成的订阅 compositeDisposable.clear() loadDish.value=true // 原有逻辑保持不变 ... }
内容的提问来源于stack exchange,提问作者Rudra Raina
相关产品推荐
相关产品推荐

