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

For循环数据重复问题求助:服务器返回3条数据却显示6条

问题排查与修复方案

你的数据重复问题主要由以下几个代码逻辑问题导致:

核心原因

  • giftsArray未清空直接追加数据:每次调用getGifts()并收到服务器响应时,你直接往giftsArray里添加新数据,但没有先清空之前的内容。如果这个方法被触发多次(比如页面重新加载、事件重复绑定),旧的3组数据会保留,新的3组又被追加,最终变成6组。
  • 单例缓存的引用复用问题:Singleton中的cache直接指向giftsArray对象,当giftsArray重复添加数据时,缓存里的内容也会跟着重复。而且如果getGifts()被多次执行,每次都会往同一个缓存列表里塞数据,不会覆盖原有内容。
  • 事件可能重复绑定:如果getGifts()被多次调用,会重复绑定initializeRoom事件。当服务器发送数据时,所有绑定的Listener都会执行一次,导致数据被重复添加多次。

修复步骤

1. 每次获取数据前清空数组

在解析JSON数据之前,先清空giftsArray,确保每次都是全新的数据集:

public void getGifts() {
    Communicator.getInstance().on("initializeRoom", new Emitter.Listener() {
        @Override
        public void call(Object... args) {
            JSONDictionary response = (JSONDictionary) args[0];
            String str = response.get("data").toString();
            try {
                // 关键:先清空数组,避免旧数据残留
                if (giftsArray == null) {
                    giftsArray = new ArrayList<>();
                } else {
                    giftsArray.clear();
                }
                
                JSONObject dataJSo = new JSONObject(str);
                JSONArray giftsData = dataJSo.getJSONArray("gifts");
                for (int i = 0; i < giftsData.length(); i++) {
                    JSONObject gifts = (JSONObject) giftsData.get(i);
                    Integer giftsId = gifts.getInt("id"); // 用getInt更安全,避免类型转换异常
                    Integer giftsPrice = gifts.getInt("price");
                    String giftsMinLevel = gifts.getString("minLevel");
                    String giftsUrl = gifts.getString("urlFile");
                    giftsArray.add(new GiftsModel(giftsId, giftsPrice, giftsUrl, giftsMinLevel));
                }
                Singleton.instance().cache = giftsArray;
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
    });
}

2. 优化单例的缓存逻辑

为了避免缓存和giftsArray的引用关联问题,可以在赋值缓存时创建新的ArrayList副本,这样后续修改giftsArray不会影响缓存内容:

// 替换原有的缓存赋值代码
Singleton.instance().cache = new ArrayList<>(giftsArray);

同时,建议给Singleton的cache做初始化,避免空指针:

public class Singleton {
    private Singleton() {
        // 初始化空的缓存列表
        cache = new ArrayList<>();
    }
    
    // 改成线程安全的双重检查锁实现(推荐)
    private static volatile Singleton obj = null;
    public static Singleton instance() {
        if (obj == null) {
            synchronized (Singleton.class) {
                if (obj == null) {
                    obj = new Singleton();
                }
            }
        }
        return obj;
    }
    
    public ArrayList<GiftsModel> cache;
}

3. 避免事件重复绑定

确保getGifts()只被调用一次(比如在FirstActivity的onCreate中调用一次),或者在绑定新Listener前先解绑旧的:

// 绑定前先移除旧的Listener(如果Communicator支持off方法)
Communicator.getInstance().off("initializeRoom");
Communicator.getInstance().on("initializeRoom", new Emitter.Listener() {
    // ... 你的逻辑代码
});

内容的提问来源于stack exchange,提问作者O.D

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:56:37