大家都见过这样的代码:

看起来很优雅,对吧?
但当你点进 BaseActivity:
👉 2000 行 👉 十几个功能混在一起 👉 没人敢改
很多 Android 项目,都是这样"慢慢烂掉"的。
1. BaseActivity 最大的问题:它构建了逻辑黑盒
BaseActivity 最大的"优点":
👉 把公共逻辑抽走 👉 让页面看起来很干净
但问题是:
它把复杂度从"代码里"转移到了"理解成本里"。
你再也无法一眼看懂一个页面:
- 页面到底做了什么?
- 有哪些自动执行的逻辑?
- 有哪些是继承带来的副作用?
你只能:
👉 点进 BaseActivity 👉 再找 override 👉 再推断执行顺序
代码变少了,但理解成本大幅增加。
2. BaseActivity,本质是"全局强绑定"
BaseActivity 里通常会有:
- Loading
- 网络监听
- 埋点
- 权限处理
- Toolbar
问题不是这些功能不好,而是:
它们被强制注入到所有页面。
但现实是:
- 有的页面不需要 Loading
- 有的页面不需要埋点
- 有的页面逻辑完全不同
一旦继承:
👉 所有页面被绑定在同一套行为上
更严重的是:
👉 修改 BaseActivity,会影响整个应用
这会让任何改动都变成高风险操作。
3. 真正的问题:用继承解决了组合问题
现代架构更强调:
组合优于继承(Composition > Inheritance)
但 BaseActivity 的做法是:
👉 把各种能力写进继承链
这会导致:
- 能力无法拆分
- 行为难以控制
- 逻辑难以替换
继承让能力"默认存在", 而组合让能力"按需使用"。
4. 为什么 BaseActivity 一定会膨胀
BaseActivity 的演化路径通常是:
- 一开始只放通用逻辑
- 团队成员逐渐往里面添加功能
- 类越来越大
- 没人敢删除或重构
- 新需求继续往里叠加
最终会变成一个:
- 所有人依赖
- 但没人完全理解
- 更没人敢修改
的核心类。
5. 正确做法:用组合替代 BaseActivity
不要再问:
👉 "这段逻辑要不要写进 BaseActivity?"
应该问:
👉 "这个能力应该属于哪一层?"
数据能力 → Repository + Flow

状态管理 → ViewModel

依赖装配 → DI(Koin / Hilt)

UI 只负责消费状态

6. 一切"Base能力"的正确归属
| 能力 | 正确归属 |
|---|---|
| Toast / 键盘 | Extension |
| 埋点 | LifecycleObserver |
| 网络 / 权限 | Repository |
| UI 状态 | ViewModel |
| 依赖管理 | DI |
能力应该被拆分,并按职责归属,而不是集中放在一个基类中。
7. 不只是 BaseActivity,BaseViewModel 也需要警惕
很多团队开始意识到 BaseActivity 的问题,但忽略了:
同样的设计问题,也会出现在 BaseViewModel 中。
典型写法:

然后所有 ViewModel 继承它。
问题在哪里?
这种写法实际上在做一件事:
👉 强行统一所有页面的业务模型
但现实情况是:
- 不同页面的 loading 形态不同
- 错误处理方式不同
- 并发和状态管理需求不同
当这些逻辑被写进 BaseViewModel:
👉 ViewModel 不再定义自己的状态 👉 而是被基类约束
更合理的方式
每个 ViewModel 自己定义状态:

不建议在viewModel里处理异常,这里只是demo
BaseViewModel 可以做什么?
可以存在,但需要限制职责:
只用于承载技术能力,例如:
- 协程封装
- 调度器管理
- 日志能力
而不应该包含:
- UI 状态
- 业务逻辑
- 通用请求模型
8. 总结
架构的本质是解耦。
在现代 Android 架构中,更合理的方式是:
- 用 Repository 承载数据能力
- 用 ViewModel 管理状态
- 用 DI 组织依赖
- 用组合替代继承
核心思路是:
👉 不要集中能力 👉 而是拆分能力,要按职责组合