Flutter赋能海狸IM:打造高性能跨平台移动体验
Flutter重构的海狸IM移动端,核心场景体验明显提升。消息列表滑动、多媒体发送、音视频通话这些之前需要花大力气优化的功能,现在变成了"默认就挺好"。这篇文章从技术选型和实际效果的角度,聊聊Flutter给海狸IM带来了什么。
渲染性能:Skia绘制的优势
IM应用最核心的交互就是消息列表。消息类型多(文本、图片、表情、文件、语音),每条消息的布局还不一样,滑动的时候要保证流畅不卡顿。
Flutter的UI渲染走的是Skia引擎,直接在Canvas上绘制,不存在WebView的JS桥接损耗,也不存在原生控件的布局传递开销。这种渲染方式的优势体现在:
- 消息列表往上滑动,帧率稳定在60fps,即使是2000条消息的长列表
- 连续发十几条消息,列表不卡顿,状态更新及时
- 图片缩略图加载是异步的,不阻塞主线程,用户操作流畅
图片缓存用了 cached_network_image 配合 flutter_cache_manager,本地命中率高的话根本不用走网络,加载速度明显提升。

本地数据库:Drift带来的数据持久化能力
之前Uniapp版本里,本地存储用的是key-value结构,消息多了查起来很费劲。Flutter版本换了Drift,这是个SQLite ORM,支持类型安全的SQL查询。
消息表设计与PC端保持一致,包含消息ID、会话ID、消息类型、发送状态等字段,支持离线重试和消息排序。消息按会话ID建了索引,查询历史消息直接SQL搞定,速度快。
离线的时候用户也能看之前的消息,联网后自动同步增量。数据库表结构和PC端保持一致,这样多端数据互通的时候格式不用转换。

音视频通话:LiveKit集成
这部分是从零做的。Flutter端集成了 livekit_client,和后端的LiveKit服务对接。核心流程封装在 CallBusiness 里:
- 用户发起通话 → 调用后端API创建room
- 获取token和room信息
- Flutter端连接LiveKit房间
- 订阅远端用户的音视频轨道
发起通话时后端创建room,返回token和URL,Flutter端直接连接。音频视频轨道的订阅和发布都封装好了,UI层只需要调用 makeCall 或者响应来电事件。

状态管理:BLoC的实践
Flutter版本选了BLoC做状态管理。一开始担心代码量变大,实际用下来发现单向数据流在复杂场景下确实更好维护。
聊天页面的状态管理采用事件驱动模式,收到新消息、发送失败、消息已读------每个操作都是明确的事件,状态变更有据可查。这种方式的好处是状态变化可追溯,测试也方便。

数据同步:增量拉取 + 本地优先
Flutter端和PC端共用后端接口,数据格式完全一致。同步策略是增量拉取,本地优先响应。
启动流程大概是:
- WebSocket连接成功后,先进入同步模式
- 根据各模块的版本号,调用
/api/chat/sync等接口拉取增量数据 - 新消息暂存到内存队列,等同步完成再写入数据库
- 同步完成,UI自动刷新
这套机制参考了商业IM的设计,实现起来不算简单,但效果是实打实的------重登之后不用等全量数据返回,消息列表秒开。

依赖注入:GetIt
代码里用了 get_it 做依赖注入。好处是解耦,测试的时候可以mock,模块之间的依赖关系也清晰。
模块按功能划分,chat、friend、call各有自己的Business类,职责单一。核心依赖集中注册,包括业务层、存储、数据库、网络和服务等模块。

实际效果
说了这么多技术实现,最终还是要看用户体验。Flutter版本跑起来:
- 消息列表滑动流畅度明显提升,2000条消息测试过不卡
- 图片、文件发送有本地缓存,速度快,用户体验好
- 音视频通话功能完整,语音通话、视频通话都支持,质量稳定
- 离线消息自动同步,不用手动刷新,重登后消息列表秒开
- 启动速度在中等配置手机上大约2-3秒,比原生稍慢但可以接受
包体积比H5大是事实,但换来的性能和功能完整性是值得的。







相关链接
项目源码:
- 后端源码:https://github.com/wsrh8888/beaver-server
- 移动端Flutter源码:https://github.com/wsrh8888/beaver-flutter
- 移动端旧版源码:https://github.com/wsrh8888/beaver-unaipp
- PC端源码:https://github.com/wsrh8888/beaver-desktop.git
- 后台管理系统源码:https://github.com/wsrh8888/beaver-manager
学习资源:
核心教学视频: