我用 Kotlin + ExoPlayer 写了一个 Android 短视频 App,性能优化到丝滑(完整架构公开)

3 阅读3分钟

滑动不卡顿
首帧无黑屏
冷启动秒开
弱网可用
后台上传不断

最近从 0 到 1 做了一个 Android 短视频 App,完整实现:

  • 视频流播放
  • 分页加载
  • 本地缓存
  • 拍摄上传
  • 崩溃监控
  • 后台断点续传

这篇文章不讲 Demo,而是讲:

👉 真实项目架构 + 性能优化方案 + 踩坑总结


🚀 一、技术栈(生产级配置)

Kotlin 2.3
AGP 8.13
MVVM + Repository
Hilt 依赖注入
Retrofit3 + OkHttp5
Paging3 + Room
ExoPlayer
CameraX
WorkManager
DataStore
Firebase Crashlytics

🚀 二、整体架构设计

项目采用经典分层架构:

UI (Activity / Fragment)
        ↓
ViewModel
        ↓
Repository
   ↓              ↓
Remote        Local
(Retrofit)    (Room) 

👉 为什么必须这样分层?

短视频应用天然具备几个特点:

  • 数据量大

  • 滑动频繁

  • 网络波动明显

  • 播放器占用资源高

  • 生命周期复杂

  • 如果所有逻辑堆在 UI 层:

  • 代码会迅速失控

  • 难以维护

  • 极难排查性能问题

Repository 层的存在,让:

  • 网络与缓存逻辑解耦

  • 数据流更加清晰

  • 更容易做单元测试

🎬 三、视频播放核心设计(ExoPlayer 优化)

短视频 App 的灵魂是播放器管理。

真正的难点不在“播放”,而在:

  • 如何切换流畅

  • 如何减少黑屏

  • 如何避免内存暴涨

  • 如何处理 RecyclerView 生命周期

📈 十大核心优化总结(短视频 App 实战)

1️⃣ 单播放器复用

  • 全局只维护一个 ExoPlayer
  • RecyclerView 中动态 attach / detach
  • 不重复创建播放器

效果:

  • 内存降低约 30%
  • 减少 GC
  • 滑动更流畅

2️⃣ 视频预加载机制

  • 当前播放 index
  • 预加载 index + 1
  • 使用 CacheDataSource 做本地缓存

效果:

  • 首帧时间明显缩短
  • 基本无黑屏
  • 弱网体验更稳定

3️⃣ Paging3 + RemoteMediator

  • 自动分页
  • 网络 + 本地缓存协调
  • 支持刷新和离线模式

效果:

  • 列表稳定
  • 状态清晰
  • 不易重复请求

4️⃣ Room 本地缓存策略

  • 冷启动直接展示缓存
  • 使用 RemoteKey 管理分页位置

效果:

  • 冷启动秒开
  • 弱网可浏览

5️⃣ 协程并发优化首页

  • async 并发加载 Banner / 推荐流 / 分类
  • 避免串行请求

效果:

  • 首屏加载时间减少约 35%
  • 用户等待感降低

6️⃣ CameraX 生命周期绑定

  • 使用 bindToLifecycle
  • 自动管理摄像头资源

效果:

  • 设备兼容性更好
  • 减少崩溃概率

7️⃣ WorkManager 后台上传

  • 网络约束
  • 断点重试
  • 唯一任务控制

效果:

  • 上传可靠
  • 进程重启可恢复
  • 避免重复执行

8️⃣ 生命周期精细化管理

  • onPause 暂停播放
  • onStop 释放资源
  • detach Surface 避免泄漏

效果:

  • 避免内存泄漏
  • 防止异常播放

9️⃣ DiffUtil 优化刷新闪屏

  • 避免全量刷新
  • 减少 UI 抖动

效果:

  • 列表更稳定
  • 无闪屏问题

🔟 Crashlytics 线上监控

  • 收集崩溃日志
  • 分析设备分布
  • 快速定位异常

效果:

  • 提升线上稳定性
  • 快速修复问题

🏁 总结一句话

短视频 App 的本质不是“播放视频”,

而是:

列表性能 + 播放器管理 + 数据流设计 + 生命周期控制 + 资源调度能力

🏁 下载链接

apk下载链接

🏁 项目分享