Android:优化Volley请求填充RecyclerView,解决重复数据问题
解决Volley重复请求导致RecyclerView数据重复的问题
嘿,这个问题我之前帮不少开发者解决过——核心就是重复触发的Volley请求都成功回调了,而且每次都往数据源里追加数据,加上你没做请求状态的拦截,自然就出现CardView重复的情况了。给你两个最常用的解决方案,按需选就行:
方案一:添加请求状态锁,禁止并发请求
这个思路最直接:给请求加个"正在进行中"的标记,在请求未完成时,点击刷新按钮直接忽略,避免重复发起请求。
代码示例:
// 定义全局变量,标记请求状态 private boolean isRequestInProgress = false; private RequestQueue mRequestQueue; private List<YourDataModel> mDataList = new ArrayList<>(); private YourRecyclerViewAdapter mAdapter; // 你的刷新方法(绑定到工具栏刷新按钮) public void refreshData() { // 如果当前正在请求,直接返回,不执行后续逻辑 if (isRequestInProgress) { return; } // 标记请求开始 isRequestInProgress = true; // 刷新前清空旧数据(这一步很重要!不然新数据会追加在旧数据后面) mDataList.clear(); mAdapter.notifyDataSetChanged(); // 构建Volley请求 StringRequest stringRequest = new StringRequest(Request.Method.GET, YOUR_API_URL, response -> { // 解析接口返回的数据,添加到数据源 parseResponseAndAddData(response); // 更新RecyclerView mAdapter.notifyDataSetChanged(); // 请求完成,解除状态锁 isRequestInProgress = false; }, error -> { // 请求失败也要解除状态锁!不然用户后续无法再触发刷新 isRequestInProgress = false; // 处理错误提示 Toast.makeText(this, "数据刷新失败", Toast.LENGTH_SHORT).show(); }); // 添加到请求队列 mRequestQueue.add(stringRequest); } // 你自己的解析数据方法 private void parseResponseAndAddData(String response) { // 这里写你的JSON解析逻辑,把解析后的对象添加到mDataList }
方案二:取消正在进行的旧请求,发起新请求
如果你的需求是:用户点击刷新时,不管之前的请求有没有完成,都取消旧请求,直接发起新的请求。那可以给Volley请求设置Tag,每次刷新前取消队列中相同Tag的请求。
代码示例:
// 定义请求唯一Tag,避免和其他请求冲突 private static final String REFRESH_REQUEST_TAG = "data_refresh_request"; private RequestQueue mRequestQueue; private List<YourDataModel> mDataList = new ArrayList<>(); private YourRecyclerViewAdapter mAdapter; public void refreshData() { // 取消队列中所有带有该Tag的请求(也就是之前未完成的刷新请求) mRequestQueue.cancelAll(REFRESH_REQUEST_TAG); // 清空旧数据 mDataList.clear(); mAdapter.notifyDataSetChanged(); // 构建新的Volley请求 StringRequest stringRequest = new StringRequest(Request.Method.GET, YOUR_API_URL, response -> { parseResponseAndAddData(response); mAdapter.notifyDataSetChanged(); }, error -> { Toast.makeText(this, "数据刷新失败", Toast.LENGTH_SHORT).show(); }); // 给请求设置Tag stringRequest.setTag(REFRESH_REQUEST_TAG); // 添加到队列 mRequestQueue.add(stringRequest); }
额外注意点
- 一定要清空旧数据:不管用哪种方案,刷新操作都应该先清空原来的数据源,再添加新数据。不然就算只触发一次请求,新数据也会和旧数据叠加,导致重复显示。
- 错误回调也要处理状态:方案一中,如果请求失败但没把
isRequestInProgress设回false,用户后续点击刷新按钮会完全没反应,这点一定要注意。 - Tag不要重复:方案二中,每个类型的请求要用独立的Tag,避免误取消其他业务的请求。
内容的提问来源于stack exchange,提问作者RFA
相关产品推荐
相关产品推荐

