《海外社交 IM 项目》深度技术复盘

112 阅读4分钟

一、项目背景与定位

海外轻量级社交 IM 应用,支持单聊、消息漫游、离线推送,目标用户为欧美年轻群体。

从 0 到 1 独立开发,3 个月内完成并上线 App Store 与 Google Play。

核心挑战

  • 跨平台一致性(iOS/Android 表现一致)
  • 海外网络环境复杂(弱网、高延迟)

二、架构设计演进

1. 初始阶段:MVC 分层架构搭建,完成项目基建设

初期采用GetX框架,搭建MVC分层架构,优先实现常用底层工具类:网络类(Dio)、本地存储类(MMKV)、通知类(EventBus)等。

分层架构采用模块化分层,自顶向下顺序依赖。 MVC实现UI与逻辑解耦。 image.png

image.png

2. 攻坚阶段:IM核心流程UML图

公司的规模很小,一个人干真是亚历山大。参考NIMSDK的IM Demo,针对需求完成核心的IM流程图。

实现im_core模块,分别包含message_manager,session_manager,管理消息和会话。

问题暴露

由于采用了模块化分层的方案,导致A模块想要引用B模块的功能,无法直接引用或者说直接A->B的话,A\B属于同一层级的模块。A->B打破了模块化分层,自顶向下的依赖原则。

改进: 随着功能增多,引入 get_it + injectable 实现依赖注入:

解耦模块依赖

// 注册
GetIt.I.registerSingleton<MessageRepository>(MessageRepositoryImpl());

// 使用
final repo = GetIt.I<MessageRepository>();

三、核心技术难点与突破

难点 1:WebSocket 高可用与断线重连

问题:海外网络不稳定,频繁断连导致消息丢失。

原方案:简单定时重连 → 失败率高。

优化方案

  1. 指数退避重连reconnectDelay = min(30s, base * 2^retryCount)
  2. 心跳保活:每 30s 发送 ping,超时 3 次触发重连
  3. 消息补偿机制:重连后主动拉取 last_msg_id 之后的消息
  4. 本地缓存兜底:未确认消息存数据库,恢复后重发

成果

  • 断线恢复成功率从 72% → 98.5%
  • 消息丢失率 < 0.1%

难点 2:消息列表高性能渲染

问题:长列表滚动卡顿,尤其在低端 Android 机上。

分析

  • ListView.builder 虽然懒加载,但 Widget 结构复杂
  • 每条消息包含头像、时间、内容、状态,嵌套层级深
  • 图片加载未节流

优化措施

优化项方案效果
Widget 结构提取 const + const 构造函数减少重建
图片加载cached_network_image + fadeInDuration: 0避免闪烁
滚动性能addAutomaticKeepAlives: false + cacheExtentFPS 提升 40%

关键代码

ListView.builder(
  cacheExtent: 500, // 预加载范围
  itemExtent: 60,   // 固定高度,避免 layout 计算
  ...
)

难点 3:消息同步

每条消息携带唯一的msgID,需要确保用户离线状态下收到的消息不丢失。

方案:

NIMSDK的服务端已经提供了消息存DB的功能,我需要拿到last_msg_id,App启动后根据last_msg_id拉取未读消息,再对消息列表进行本地去重后渲染到消息列表。

难点 4: 设计礼物播放插件

在im聊天窗口,可以送对方礼物,购买礼物发送后,在聊天窗口会出现礼物播放的特效。

基于腾讯的flutter插件flutter_vap封装了一个礼物播放的插件。

插件源代码: github.com/mrginpadd/w…

结合了 视频播放 + 状态管理 + 播放队列 + 资源优化, 支持多个礼物按顺序播放

四、性能与稳定性保障

Firebase Analytics

为项目集成FireBase实现埋点和上报异常。

五、部分界面展示

image.png

image.png

image.png

image.png

六、总结:我的成长和收获

自从Oppo的TeamTalk项目组辞职去义乌电商创业之后,中间离开it行业差不多8个月。

这是回归IT的第1个项目,也是第1个完全独立从0搭建并上线的项目。

是我转型的一个转折点,彻底摆脱了学生心理。

之前校招零基础进TeamTalk项目组,组内二十多个and + iOS开发人员,全是5~10年经验的中高级工程师,我和同事B同为应届生,面对着经验上的巨大差距,免不了心理上有巨大的落差,做事情畏畏缩缩。

直到遇到这个项目让我有机会尝试了全链路的开发流程,一切都在我脑中清晰了起来。

想到之前在TT组,每天下班都开代码评审会,开到七八点,同事们颇有微词。Leader说:“之所以开会,是希望我们组是一个成长型的组......”。当时不理解。直到自己独立开发,每一场开会的内容,同事讲的代码或者方案或者一个不经意的小细节,都在我脑中不断的浮现出来。

教育在此刻完成了闭环......