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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 07:57:04