Retrofit搜索结果叠加问题:如何仅显示最新搜索结果?
解决搜索结果追加而非替换的问题
问题描述
通过EditText输入关键词调用API获取新闻数据,首次搜索结果显示正常,但后续搜索时新结果会追加到旧结果的末尾,而非仅展示当前搜索词对应的内容。尝试添加@Headers("Cache-Control: no-cache")解决缓存问题,但无效。
问题根源
问题并非网络缓存导致,而是客户端的列表状态管理逻辑存在漏洞:
- ViewModel发起新搜索时,未正确重置之前的结果状态,导致旧数据未被清空
- 未处理搜索词为空的场景,旧列表持续保留
修复步骤
1. 完善ViewModel的搜索状态重置逻辑
在发起新搜索请求前,先发送Loading状态,确保后续的Success状态携带全新结果,覆盖旧数据。补全ViewModel核心代码:
class NewsViewModel : ViewModel() { private val _searchNews = MutableLiveData<Resource<NewsResponse>>() val searchNews: LiveData<Resource<NewsResponse>> = _searchNews fun searchNews(query: String) { // 新搜索发起时重置状态,通知UI开始加载 _searchNews.postValue(Resource.Loading()) viewModelScope.launch { try { val response = newsRepository.searchNews(query) if (response.isSuccessful) { // 提交全新的搜索结果 _searchNews.postValue(Resource.Success(response.body())) } else { _searchNews.postValue(Resource.Error("搜索请求失败")) } } catch (e: Exception) { _searchNews.postValue(Resource.Error(e.message ?: "未知错误")) } } } }
2. 处理搜索词为空的场景
在Fragment的文本监听中,当搜索词为空时直接清空列表:
var job: Job? = null binding.etSearchNews.addTextChangedListener { editable -> job?.cancel() job = MainScope().launch { delay(Constants.SEARCH_DELAY) val query = editable.toString().trim() if (query.isNotEmpty()) { viewModel.searchNews(query) } else { // 搜索词为空时清空列表 newsAdapter.differ.submitList(emptyList()) } } }
3. 确保Adapter正确替换列表
当前代码中response.articles.toList()已经生成新列表实例,但如果仍存在追加问题,可临时在收到成功结果时先提交空列表再提交新列表(仅用于排查,正常情况下无需此操作):
viewModel.searchNews.observe(viewLifecycleOwner) { when (it) { is Resource.Success -> { hideProgressBar() it.data?.let { response -> newsAdapter.differ.submitList(emptyList()) newsAdapter.differ.submitList(response.articles.toList()) } } is Resource.Error -> { hideProgressBar() // 可添加错误提示逻辑 } is Resource.Loading -> { showProgressBar() } } }
4. 验证API请求参数
确认Retrofit接口每次请求都携带了最新的搜索词,当前你的API代码已经正确传入@Query("q") query参数,这部分无需修改。
内容的提问来源于stack exchange,提问作者Mert
相关产品推荐
相关产品推荐

