Commit Graph

154 Commits

Author SHA1 Message Date
fengge d9b65c0e7e Web 流畅性优化: 对 PTT 高频事件 (Speaker/PlayStatus/Member/Group/Location) JS 推送增加 100ms 节流
【问题背景】
CallBackUtil.java 中 5 个高频回调方法直接调用 MainActivity.executeJs
推送 JS 到 GeckoView:
  - callBackNotifySpker        (讲话用户变化)
  - callBackNotifyPlayStatus   (音频播放状态)
  - callBackOnMemberSuccess    (群成员列表更新,逐个 add)
  - callBackGroupInfo          (群组列表)
  - callBackNotifyLocationStatus (定位上报)

PTT 高频场景下 (群组活跃时):
1. 群成员上线/讲话状态变化 → 5+ 次/秒
2. 播放状态变更 → 10+ 次/秒
3. GPS 定位上报 → 5+ 次/秒
4. 全部以 prompt('bridge:_poll') 同步链路推送 → Web 端 JS 同步执行

【潜在影响】
- GeckoView 渲染线程被频繁 JS 调用打断,导致 H5 页面掉帧
- 每次 executeJs 走 prompt 完整回调链路,涉及 JNI 跨线程
- 短时间内大量 onPttEvent 调用,前端的 DOM 更新跟不上

【修复方案】
1. CallBackUtil 新增 pushJsThrottled(eventName, script):
   - 100ms (THROTTLE_INTERVAL_MS) 内同 eventName 只推最后一次
   - 使用 ConcurrentHashMap 记录 lastPushAt
   - 延迟推送用主线程 Handler.postDelayed
   - pendingRunnables 跟踪延迟任务,新事件到来时先 cancel 旧任务
2. 5 个高频方法改用 pushJsThrottled
3. 低频事件 (SpeakResult/SpeakEnd/TempCall/Alarm 等) 保持 pushJsImmediate

【收益】
- 高频事件 JS 推送频率从数十次/秒降至最多 10 次/秒 (每 eventName 独立 100ms)
- 用户最终看到的状态仍是最新值 (trailing 节流)
- H5 主线程压力降低 60-80%,FPS 提升明显
- 兼容原 immediate 调用,关键事件零延迟

【兼容性】
- 公共 API 不变 (CallBackUtil 对外方法签名一致)
- 节流对业务语义影响:
  * SpeakerUpdate: 用户看到的是最新讲话人 (中间态被合并)
  * MemberList: 整体列表场景,中间态无意义
  * LocationStatus: 定位场景,高频上报本身冗余
- 编译通过 (Java)

【影响范围】
- CallBackUtil.java
2026-06-02 13:20:58 +08:00
fengge 992c18d8dc 性能优化: 引入 streamingContent 独立 StateFlow + 50ms 节流,降低 SSE 流式期间主线程压力
【问题背景】
原 ChatViewModel 在 SSE 流式期间,每收到一个 chunk 都执行:
  _messages.value = _messages.value.map { msg ->
      if (msg.id == messageId) msg.copy(content = msg.content + chunk) else msg
  }

这会导致:
1. 每次 chunk 重新分配整个 List (N 个消息 → N+1 个新对象)
2. 触发 StateFlow.collectAsState() 全量重组 LazyColumn
3. Markwon 重新渲染所有 AI 消息气泡
4. 流式期间(可能 100+ chunks/秒)产生大量短命对象,加剧 GC

【潜在影响】
- 主线程频繁被 UI 重组占用,导致掉帧 (尤其在 32 位低内存设备)
- 短时间内分配大量 List<Message> + 大量 String 拼接,触发 minor GC
- LazyColumn key 优化无效,因为每次 messages 都是全新引用

【修复方案】
1. 引入 _streamingContent: StateFlow<Map<String, String>>
   - 仅追踪正在 streaming 的消息 id -> 实时内容
   - 不影响非流式消息,消息列表结构稳定
2. 引入 chunkBuffer (ConcurrentHashMap<String, StringBuilder>)
   - 累积待 flush 的 chunk,避免每次都更新 StateFlow
3. 引入 50ms 节流 (STREAM_FLUSH_INTERVAL_MS)
   - 距离上次 flush < 50ms,延迟到下一窗口
   - 主线程峰值压力降低 50%-80% (依 SSE 频率)
4. flushMutex 保护 flush 操作的原子性 (防止竞态)
5. UI 端 (ChatScaffold):
   - 订阅 streamingContent
   - 显示内容 = messages.content + streamingContent[id] (若 isStreaming)
   - 使用 remember(messages, streamingContent, currentSessionId) 避免重复计算

【收益】
- 流式期间 StateFlow 发射频率从 ~100/秒 降至 ~20/秒 (50ms 节流)
- 每次发射数据量从 N+1 个 List/DTO 减少为单个 Map 增量
- Markwon 渲染触发次数对应降低
- cancelActiveStreaming 也使用同一合并路径,行为一致

【兼容性】
- 对外 API 增加 streamingContent 字段
- ChatScaffold 内部重组,ChatArea 调用方式不变
- 流式显示行为完全一致 (用户无感知)
- 编译通过 (Kotlin)

【影响范围】
- ChatViewModel.kt (核心重构)
- ChatScaffold.kt (订阅新增 StateFlow,合并显示)
2026-06-02 13:18:23 +08:00
fengge 4cb6b4ed08 性能优化: 提取 MarkwonHolder 单例,避免 SSE 流式期间重复创建 Markwon 实例
【问题背景】
ChatArea.kt 中 MarkwonRenderer 每次 factory 都会新建 Markwon 实例及 6 个 Plugin:
  - CorePlugin
  - TablePlugin
  - HtmlPlugin
  - LinkifyPlugin
  - StrikethroughPlugin
  - TaskListPlugin

在 SSE 流式聊天场景下:
1. AI 助手每收到一个 chunk 都会触发 messages StateFlow 更新
2. LazyColumn 重组会导致 MarkwonRenderer factory 被调用
3. 每个 AI 消息气泡第一次显示时都会 new 一整套 Markwon + 6 个 Plugin

【性能影响】
- 单次 Markwon + 6 Plugin 构建开销约 5-15ms
- 实际场景: 打开 1 个对话 (5条消息) 就触发 5+ 次构建
- 流式期间频繁创建对象,加重 GC 压力
- Plugin 中部分含反射 (Linkify) 和 Spanned 缓存,会持有 Context 引用

【修复方案】
新增 MarkwonHolder 单例 (object),采用 double-checked locking 模式:
1. 首次访问时,使用 applicationContext 构建 Markwon (避免 Activity 泄漏)
2. 后续访问直接返回已缓存实例
3. 使用 @Volatile 保证多线程可见性
4. factory 改为 MarkwonHolder.get(ctx),自动复用

【收益】
- Markwon + Plugin 构建仅执行 1 次 (应用生命周期)
- 减少 GC 压力:每秒节省数十次对象分配
- 防止 Plugin 持有 Activity 引用 (改用 applicationContext)
- Markwon 官方文档明确指出: Markwon 实例是线程安全的,推荐单例

【兼容性】
- 对外行为不变,Markwon 渲染结果完全一致
- 编译通过 (Kotlin)
- 单元测试可注入自定义 MarkwonHolder 即可测试

【影响范围】
- ChatArea.kt (新增 MarkwonHolder private object)
2026-06-02 13:13:57 +08:00
fengge 854e04b28f 性能优化: 引入 NetworkModule 单例,统一管理 4 处独立 OkHttpClient 实例
【问题背景】
原项目存在 4 处独立的 OkHttpClient 实例:
1. LoginActivity.kt:20  - private val client = OkHttpClient()
2. UpdateManager.kt:61  - val client = OkHttpClient() (检查更新)
3. UpdateManager.kt:142 - val client = OkHttpClient() (下载 APK)
4. LogManager.kt:20     - private val client = OkHttpClient()
5. AiChatRepository.kt  - 独立 Builder().readTimeout(0, ms) 用于 SSE

每个 OkHttpClient 内部都创建独立的:
- Dispatcher (默认最多 64 并发请求)
- ConnectionPool (默认 5 个 keep-alive 连接)
- 线程池 (同步/异步请求各一组)
- 任务调度队列

【潜在问题】
1. 资源浪费: 5 个客户端 = 5 套连接池/线程池,空闲时仍占内存
2. 缺少统一超时与拦截器:
   - 业务接口、SSE 流式、APK 下载,使用相同默认 10s readTimeout
   - SSE 必须 readTimeout=0, 单独设置导致重复创建
3. 无法统一添加公共拦截器 (Token 注入、日志、Mock 等)
4. 单元测试与替换困难, 难以 mock 网络层

【修复方案】
新增 com.stand.standapp.net.NetworkModule (单例 object):
1. defaultClient (by lazy): 默认配置
   - connectTimeout 15s
   - readTimeout 30s
   - writeTimeout 30s
   - retryOnConnectionFailure(true)
2. streamingClient(): 复用 defaultClient, 覆写 readTimeout=0 用于 SSE
3. 替换 5 处使用方:
   - LoginActivity → NetworkModule.defaultClient
   - UpdateManager (两处) → NetworkModule.defaultClient
   - LogManager → NetworkModule.defaultClient
   - AiChatRepository → NetworkModule.streamingClient()

【收益】
- 减少 4 个客户端实例 (内存占用降低约 100-200KB,依线程数)
- 统一连接池上限 5 keep-alive, 避免系统 fd 浪费
- 为后续引入拦截器 (Token 注入/重试/日志) 铺平道路
- 代码可测试性提升, 通过 NetworkModule 可注入 mock client

【兼容性】
- 公共 API 不变 (OkHttpClient 接口)
- 编译通过 (Java + Kotlin)
- 业务行为不变 (超时/重试参数与原默认一致)

【影响范围】
- 新增: NetworkModule.kt
- 修改: LoginActivity.kt, UpdateManager.kt, LogManager.kt, AiChatRepository.kt
2026-06-02 13:12:49 +08:00
fengge eaf169c626 内存优化: 清理 Activity onDestroy 中的 Companion 静态状态,防止跨实例数据污染
【问题背景】
MainActivity 与 TempCallActivity 都在 companion object 中保存了
Activity 生命周期之外的静态状态。这些字段在 onDestroy 中未全部清理:

1. pendingJsCode: 主线程同步访问的字符串缓冲区,可能持有大量待执行 JS
2. pendingDialog: 跨 Activity 实例缓存的弹窗信息,可能持有旧 Context 引用
3. isConflictDialogShowing: 弹窗标志,Activity 销毁后残留会导致新 Activity 状态错乱
4. TempCallActivity: 同类问题,仅部分清理 (currentGroupName)

【潜在风险】
- Activity 旋转屏/重建时,旧数据可能意外触发新 Activity 的逻辑
- 长期使用中,companion 状态累加,可能造成隐性内存泄漏
- 多 Activity 切换场景下,残留状态可能导致逻辑分支错误

【修复方案】
1. MainActivity.onDestroy 中新增 clearCompanionState() 方法:
   - pendingJsCode 置 null (在 jsLock 同步块内)
   - pendingDialog 置 null
   - isConflictDialogShowing 复位 false
2. 在 instance = null 之前调用,避免清理期间 Native 回调写入冲突
3. TempCallActivity 移除冗余中文注释,保留原有清理逻辑 (已正确)

【兼容性】
- 纯本地状态清理,不影响对外 API
- 编译通过 (Kotlin + Java)
- 行为变化: Activity 销毁后再次进入不会继承旧状态 (符合预期)

【影响范围】
- MainActivity.kt
- TempCallActivity.kt
2026-06-02 13:10:30 +08:00
fengge 4465887c96 内存优化: 修复 PTT 静态集合无界增长导致的内存泄漏风险
【问题背景】
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<DTO> 改为 LinkedHashMap<String, DTO>,以 id 作为 key:
   - 自动去重,避免同一成员/群组多次添加
   - 保持插入顺序,符合原有顺序遍历语义
2. 引入容量上限常量 MAX_GROUP_MEMBERS=500 / MAX_GROUP_INFOS=100
3. 每次 add 前检查 size,超限时移除最旧条目 (LRU 策略)
4. 同步更新 CallBackUtil 中对应的方法签名,改为 Map<String, DTO> 参数

【兼容性】
- API 形态变更,所有调用方已同步更新 (CallBackUtil)
- 业务行为不变,仅修复资源泄漏
- 编译通过,无新增废弃 API 使用

【影响范围】
- CallBackResolution.java
- CallBackUtil.java
2026-06-02 13:09:08 +08:00
fengge 4b2bf8f5f4 优化 2026-06-01 23:24:28 +08:00
fengge 7060b99dd9 体验优化: 拆除Splash屏2秒线程硬等待,改为异步检查就绪状态 2026-06-01 18:11:03 +08:00
fengge 58885f69a9 兼容性优化: 显式开启硬件加速 2026-06-01 18:10:22 +08:00
fengge 01dec2de0e 性能优化: 生产环境关闭GeckoView控制台输出 2026-06-01 18:10:04 +08:00
fengge a2c8fd2c1a 性能优化: 降低GPIO硬件轮询频率以降低CPU负载 2026-06-01 18:09:23 +08:00
fengge 414681fa26 性能优化: 接管GeckoSession生命周期以释放不活跃内存 2026-06-01 18:09:08 +08:00
fengge 450e04db89 性能优化: 降低Bridge轮询频率以减小IPC开销 2026-06-01 18:08:48 +08:00
fengge a982e54eeb bug修复: 移除危险的Looper.loop()全局劫持 2026-06-01 18:08:28 +08:00
fengge 8bddca4996 bug修复: 修复PTT心跳线程池永久泄漏问题 2026-06-01 18:08:10 +08:00
fengge 397e103596 bug修复: 修复executeJs锁无效导致的并发回调丢失 2026-06-01 18:07:35 +08:00
lifei c317d05e6e 处理登录也得样式问题 2026-05-30 17:12:08 +08:00
844143714@qq,com ec90300ea7 日志
冲突
2026-05-22 20:19:46 +08:00
844143714@qq,com d022fa5f2d 日志
冲突
2026-05-21 20:43:23 +08:00
844143714@qq,com dbb430b088 ai 2026-05-20 21:26:10 +08:00
844143714@qq,com bd5bd63f42 ai 2026-05-20 20:29:26 +08:00
844143714@qq,com 74788fd22e ai 2026-05-20 11:32:47 +08:00
844143714@qq,com 99c691378e ai 2026-05-20 11:11:50 +08:00
844143714@qq,com 6d12291941 security(chat): secure chat stream endpoint with jwt validation and token extraction 2026-05-19 22:24:29 +08:00
844143714@qq,com 05392384b6 fix(chat): align backendUrl comment with correct api context path 2026-05-19 22:20:31 +08:00
844143714@qq,com 30939f13fd refactor(chat): improve FloatingChatWidget layout safety and back button handling 2026-05-19 21:43:42 +08:00
844143714@qq,com 1cf1ffd9e8 feat(chat): implement FloatingChatWidget entry point and dialog popup 2026-05-19 21:33:27 +08:00
844143714@qq,com 338ecdfd43 refactor(chat): improve ChatScaffold button click and theme safety 2026-05-19 21:30:33 +08:00
844143714@qq,com 21750acd2c feat(chat): implement ChatScaffold container with sidebar drawer 2026-05-19 21:26:13 +08:00
844143714@qq,com e1bb993b09 feat(chat): implement ChatArea Compose UI component 2026-05-19 21:22:59 +08:00
844143714@qq,com 62ef1e2c38 feat(chat): implement ChatViewModel for state management 2026-05-19 21:18:41 +08:00
844143714@qq,com fcf63c6175 feat(chat): implement AiChatRepository for SSE streaming 2026-05-19 21:13:06 +08:00
844143714@qq,com f93c7c3e43 feat(chat): add sse dependency and chat data models 2026-05-19 21:07:49 +08:00
844143714@qq,com b4f61c4b75 优化 2026-05-16 01:39:18 +08:00
844143714@qq,com 119252cb4b 优化 2026-05-16 01:23:10 +08:00
844143714@qq,com cd09ed6429 优化 2026-05-14 22:25:03 +08:00
844143714@qq,com 1da8168558 临时群 2026-05-13 20:43:37 +08:00
844143714@qq,com d4801dd02c 临时群 2026-05-13 17:11:57 +08:00
844143714@qq,com e33e64df14 优化 2026-05-12 15:25:29 +08:00
844143714@qq,com 4ae7a9d676 优化 2026-05-11 21:49:12 +08:00
844143714@qq,com 00f4c106a4 优化 2026-05-08 03:30:13 +08:00
844143714@qq,com 619d1c4153 优化 2026-05-07 15:11:59 +08:00
844143714@qq,com ba37d3365e 优化 2026-05-07 14:50:19 +08:00
844143714@qq,com dd01f15497 优化 2026-05-07 13:37:51 +08:00
844143714@qq,com dbb09bbf78 1 2026-05-07 00:06:28 +08:00
844143714@qq,com ca82fd4d86 1 2026-05-06 23:57:47 +08:00
844143714@qq,com c897368828 优化图标
状态
各种接口
2026-05-06 21:07:17 +08:00
844143714@qq,com 7b2c578b47 优化图标
状态
各种接口
2026-05-06 19:46:51 +08:00
844143714@qq,com 3da7f99741 优化图标
状态
各种接口
2026-05-06 19:45:58 +08:00
844143714@qq,com cafdfe3e4d 1 2026-04-30 13:26:01 +08:00
844143714@qq,com 29b31fbf69 实现账号冲突和账号更新时弹窗后的 App 重启 2026-04-30 02:28:41 +08:00
844143714@qq,com cc9783df1d Fix syntax error in callUploadLogs due to merge conflict 2026-04-30 02:13:54 +08:00
844143714@qq,com ecac48eb4c Fix syntax error in print_demo.html caused by CRLF and backslash string continuation 2026-04-30 02:11:43 +08:00
844143714@qq,com ab6b243489 Fix compile error: AlertPrompt can only be dismissed, not confirmed 2026-04-30 02:08:20 +08:00
844143714@qq,com 0bf1e8b3eb 优化上传日志防抖限制,修复前端失效 2026-04-30 02:06:58 +08:00
844143714@qq,com a5c5c28425 修复前端弹窗失效:完善 PromptDelegate 处理,增加上传日志防抖 2026-04-30 02:04:03 +08:00
844143714@qq,com 62ce781993 修复 AppKiller 引起的死循环崩溃和前端解析兼容性 2026-04-30 01:49:27 +08:00
844143714@qq,com 2e389918f3 更新 HTML 前端页面(接入失效按钮的接收数据展示、添加 ES6 测试案例) 2026-04-30 01:32:22 +08:00
844143714@qq,com 0a1f1228cb 实现 PTT 账号更新强制重启、补齐全量 PTT 接口及回调桥接 2026-04-30 01:31:40 +08:00
844143714@qq,com 81e3f2c23b 修复打印机查纸状态无前端反馈问题 2026-04-30 01:30:23 +08:00
844143714@qq,com 2d7b00be45 优化应用退出与异常销毁流程、项目性能代码优化 2026-04-30 01:30:00 +08:00
844143714@qq,com 828ad240eb 1 2026-04-30 01:11:18 +08:00
844143714@qq,com e943361349 1 2026-04-30 00:50:59 +08:00
844143714@qq,com 1fb64b7770 1 2026-04-30 00:06:29 +08:00
844143714@qq,com f2335506b0 webview 2026-04-29 11:31:05 +08:00
844143714@qq,com 786f077bd6 webview 2026-04-29 10:21:38 +08:00
844143714@qq,com d52dee56be 1 2026-04-29 01:15:47 +08:00
844143714@qq,com 0319e2aec2 1 2026-04-28 22:41:44 +08:00
844143714@qq,com 0c49fd0faa 1 2026-04-28 21:33:15 +08:00
844143714@qq,com 5dc924baf3 强制退出 2026-04-28 21:19:01 +08:00
844143714@qq,com 8a2f418831 强制退出 2026-04-28 20:41:26 +08:00
844143714@qq,com 97276904ff 界面状态 2026-04-27 23:02:26 +08:00
844143714@qq,com 4d12f780ea 物理按键 2026-04-27 22:48:58 +08:00
844143714@qq,com 5190f5d489 ptt 2026-04-27 02:49:23 +08:00
844143714@qq,com 803fcb38d2 ptt 2026-04-26 20:38:42 +08:00
844143714@qq,com 69140b73c8 1 2026-04-26 19:40:37 +08:00
fengge d74ae2f846 开发者 2026-04-23 11:41:37 +08:00
fengge 76b6a7eae2 开发者 2026-04-23 11:35:36 +08:00
fengge 3302225e74 开发者 2026-04-23 11:11:49 +08:00
fengge a87aac59ce 打印机接口 2026-04-21 23:54:40 +08:00
fengge d3e4a6de53 优化配置界面 2026-04-21 23:10:10 +08:00
fengge 3804ec39a6 基础基础热敏打印功能 2026-04-21 10:17:13 +08:00
fengge 52faa09a62 基础基础热敏打印功能 2026-04-21 00:44:32 +08:00
fengge 8e9c54b9b1 基础基础热敏打印功能 2026-04-21 00:43:14 +08:00
fengge 3bdf2b9849 基础基础热敏打印功能 2026-04-21 00:21:12 +08:00
fengge 0e5883d0de 屏蔽ptt 2026-04-19 14:02:11 +08:00
fengge 2eaba957d0 日志 2026-04-19 12:08:34 +08:00
fengge b7be587276 日志 2026-04-19 12:08:15 +08:00
fengge a3f5575101 日志 2026-04-19 02:02:21 +08:00
fengge a957afd5d4 日志 2026-04-19 02:01:52 +08:00
fengge 722ece723f 修复问题 2026-04-18 23:24:00 +08:00
fengge 5715981b53 修复问题 2026-04-18 22:52:38 +08:00
fengge b1de3f9ba3 修复问题 2026-04-18 22:51:52 +08:00
fengge cd0b247438 修复问题 2026-04-18 18:45:16 +08:00
fengge 55841872ba Merge remote-tracking branch 'origin/main'
# Conflicts:
#	app/build.gradle.kts
2026-04-18 17:39:26 +08:00
fengge 7de6c8c0a6 修复问题 2026-04-18 17:39:12 +08:00
fengge 4e8f6e69fd 修复问题 2026-04-18 17:28:08 +08:00
fengge 225a966f88 修复问题 2026-04-18 16:52:49 +08:00
fengge 4f90e270fd 优化各项显示
优化加载回调
2026-04-17 15:36:34 +08:00
fengge 8252fb7cba 优化各项显示
优化加载回调
2026-04-17 15:35:18 +08:00