【问题背景】 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) |
||
|---|---|---|
| .. | ||
| libs | ||
| src | ||
| .gitignore | ||
| build.gradle.kts | ||
| proguard-rules.pro | ||