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
相关产品推荐
相关产品推荐

