From 4465887c96909e5ce0655762f5dc3cfcc2728b5c Mon Sep 17 00:00:00 2001 From: fengge <844143714@qq.com> Date: Tue, 2 Jun 2026 13:09:08 +0800 Subject: [PATCH] =?UTF-8?q?=E5=86=85=E5=AD=98=E4=BC=98=E5=8C=96:=20?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=20PTT=20=E9=9D=99=E6=80=81=E9=9B=86=E5=90=88?= =?UTF-8?q?=E6=97=A0=E7=95=8C=E5=A2=9E=E9=95=BF=E5=AF=BC=E8=87=B4=E7=9A=84?= =?UTF-8?q?=E5=86=85=E5=AD=98=E6=B3=84=E6=BC=8F=E9=A3=8E=E9=99=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 【问题背景】 CallBackResolution.java 中两个 static 集合 (memberInfoDtos、groupInfos) 用于暂存 PTT 引擎回调的群组/群成员信息。原实现使用 ArrayList/LinkedList, 仅在收到 groupNo==1 / memberNo==1 的边界事件时调用 clear()。 【潜在风险】 1. 若服务端漏发边界事件 (1) 或中途断流,列表将无限增长 2. 长周期运行 (消防值守台常驻) 时,Heap 中堆积大量 DTO 对象 3. 在 Android 低内存设备上 (armeabi-v7a 32位机型) 极易触发 OOM 4. 即使后续收到 clear 信号,GC 压力也会显著增加 【修复方案】 1. 将 List 改为 LinkedHashMap,以 id 作为 key: - 自动去重,避免同一成员/群组多次添加 - 保持插入顺序,符合原有顺序遍历语义 2. 引入容量上限常量 MAX_GROUP_MEMBERS=500 / MAX_GROUP_INFOS=100 3. 每次 add 前检查 size,超限时移除最旧条目 (LRU 策略) 4. 同步更新 CallBackUtil 中对应的方法签名,改为 Map 参数 【兼容性】 - API 形态变更,所有调用方已同步更新 (CallBackUtil) - 业务行为不变,仅修复资源泄漏 - 编译通过,无新增废弃 API 使用 【影响范围】 - CallBackResolution.java - CallBackUtil.java --- .../kingway/ptt/CallBackResolution.java | 21 +++++++++++++++---- .../com/example/kingway/ptt/CallBackUtil.java | 8 +++---- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/com/example/kingway/ptt/CallBackResolution.java b/app/src/main/java/com/example/kingway/ptt/CallBackResolution.java index 7fef131..e2a5942 100644 --- a/app/src/main/java/com/example/kingway/ptt/CallBackResolution.java +++ b/app/src/main/java/com/example/kingway/ptt/CallBackResolution.java @@ -5,7 +5,10 @@ import android.util.Log; import timber.log.Timber; import java.util.ArrayList; +import java.util.Iterator; +import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; @@ -17,11 +20,13 @@ public class CallBackResolution { private static String TAG = "PTT_RX"; private static String indexGroupId = "";//用户所在群组Id private static String indexGroupName = "";//用户所在群组名称 - private static List memberInfoDtos = new ArrayList<>(); + private static final int MAX_GROUP_MEMBERS = 500; + private static final int MAX_GROUP_INFOS = 100; + private static final Map memberInfoDtos = new LinkedHashMap<>(MAX_GROUP_MEMBERS); private static int speckType = 1; private static String talkId = ""; private static String talkName = ""; - private static ArrayList groupInfos = new ArrayList<>(); + private static final Map groupInfos = new LinkedHashMap<>(MAX_GROUP_INFOS); private static String oldLoginSate = "00"; private static int logNum = 0; private static long offlineTime = 0; @@ -139,8 +144,12 @@ public class CallBackResolution { CallBackUtil.callBackGroupInfo(groupId, tempTxt, groupNo, groupCount); Timber.tag(TAG).d( "at_OEM_AT_cb group info groupId: " + groupId + ", groupNo: " + groupNo+", groupCount: " +groupCount); if (1 == groupNo) groupInfos.clear(); + if (groupInfos.size() >= MAX_GROUP_INFOS) { + Iterator it = groupInfos.keySet().iterator(); + if (it.hasNext()) { it.next(); it.remove(); } + } GroupInfoDto groupInfo = new GroupInfoDto(groupId, tempTxt, groupNo, groupCount); - groupInfos.add(groupInfo); + groupInfos.put(groupId, groupInfo); } break; @@ -169,7 +178,11 @@ public class CallBackResolution { String tempTxt = unicodeToString(groupMemberName.toString()); GroupMemberInfoDto infoDto = new GroupMemberInfoDto(memberId, tempTxt, status, memberNo, haveVideo); if (memberNo == 1) memberInfoDtos.clear(); - memberInfoDtos.add(infoDto); + if (memberInfoDtos.size() >= MAX_GROUP_MEMBERS) { + Iterator it = memberInfoDtos.keySet().iterator(); + if (it.hasNext()) { it.next(); it.remove(); } + } + memberInfoDtos.put(memberId, infoDto); } break; diff --git a/app/src/main/java/com/example/kingway/ptt/CallBackUtil.java b/app/src/main/java/com/example/kingway/ptt/CallBackUtil.java index e7b5a4a..d8cae23 100644 --- a/app/src/main/java/com/example/kingway/ptt/CallBackUtil.java +++ b/app/src/main/java/com/example/kingway/ptt/CallBackUtil.java @@ -68,11 +68,11 @@ public class CallBackUtil { * 查询群组成员返回 * state true-成功, false-失败 */ - public static void callBackOnMemberSuccess(boolean state, List dtos) { + public static void callBackOnMemberSuccess(boolean state, java.util.Map dtos) { try { org.json.JSONArray arr = new org.json.JSONArray(); if (dtos != null && state) { - for (GroupMemberInfoDto dto : dtos) { + for (GroupMemberInfoDto dto : dtos.values()) { org.json.JSONObject obj = new org.json.JSONObject(); obj.put("memberId", dto.getMemberId()); obj.put("memberName", dto.getGmemberName()); @@ -128,10 +128,10 @@ public class CallBackUtil { * 返回群组集合信息 * GroupInfoDto 群组信息 * */ - public static void callBackGroupInfo (ArrayList < GroupInfoDto > groupInfoDtos) { + public static void callBackGroupInfo (java.util.Map groupInfoDtos) { try { org.json.JSONArray arr = new org.json.JSONArray(); - for (GroupInfoDto dto : groupInfoDtos) { + for (GroupInfoDto dto : groupInfoDtos.values()) { org.json.JSONObject obj = new org.json.JSONObject(); obj.put("groupId", dto.getGroupId()); obj.put("groupName", dto.getGroupName());