DEV Community

Cover image for 主流 Android 架构十年演化史——我们到底在解决什么问题? A Decade of Android Architecture Evolution: What Problem Are We Really Solving?
goodlords
goodlords

Posted on

主流 Android 架构十年演化史——我们到底在解决什么问题? A Decade of Android Architecture Evolution: What Problem Are We Really Solving?

Android 架构系列博文(共4篇)

第一篇:主流 Android 架构十年演化史——我们到底在解决什么问题?

系列导航第二篇:Lego架构——分治思想的极致实践 | 第三篇:用 Lego 架构重构商品详情页

前言:学会了所有架构,代码真的变好了吗?

从 2010 年 Android 诞生至今,主流架构至少经历了五次行业级迭代。我们背熟了 MVC 的分层,掌握了 MVP 的接口解耦,拥抱了 MVVM 的数据绑定,推崇 Clean Architecture 的依赖倒置,现在又全员转向 MVI 的单向数据流。

但一个扎心的问题是:当我们把这些架构都学了一遍、重构了一遍之后,代码就真的变好了吗?

如果你的回答是“没有”,甚至“只是换了个地方写垃圾代码”——那么这篇文章,就是为你准备的。


一、架构演化的本质:一场“减少连线”的革命

理解所有架构的演化,只需要一个极其简单的模型:强引用连线的数量,决定了系统的复杂度。

连线越多,模块间牵制越深,改动越容易引发连锁反应。历代架构,都在做同一件事——尽可能地减少连线,让依赖关系单向、清晰。

1. MVC:混乱三角(6 根连线)

作为现代架构的鼻祖,MVC 首次提出分层思想:

  • Model:数据
  • View:UI
  • Controller:逻辑

然而三者在经典实现中是两两互交的,形成了一个闭环三角形,总共产生 6 根强引用连线:

View ←→ Controller ←→ Model
↑                       ↑
└───────────────────────┘
Enter fullscreen mode Exit fullscreen mode

在 Android 中,Activity/Fragment 更是同时充当 View 和 Controller,导致上千行的"Massive View Controller"成为常态。一次数据变动可能牵动所有层,根本理不清。

2. MVP:切断直连(4 根连线)

MVP 做出了一项革命性简化:彻底禁止 View 与 Model 直接交互。

所有跨层通信必须经过 Presenter,三角形被打破,变成了线性依赖:

View ←→ Presenter ←→ Model
Enter fullscreen mode Exit fullscreen mode

连线数从 6 降到 4,复杂度立降 33%。View 只做展示,Model 只做数据,业务逻辑全在 Presenter。2015-2018 年间,这几乎拯救了整个 Android 开发社区。

3. MVVM:依赖反转(3 根连线)

MVVM 在 MVP 的基础上更进一步,引入数据绑定和可观测状态,实现依赖反转:

View → ViewModel ←→ Model
Enter fullscreen mode Exit fullscreen mode
  • View 仍持有 ViewModel 引用,但 ViewModel 不再持有任何 View 引用。
  • ViewModel 完成任务后,只更新一个可观察的数据状态,完全不知道、也不关心谁在观察。

连线数降到 3,View 与 ViewModel 之间变为单向,省去了手动 UI 更新代码和繁琐的接口定义。

这次改变的更深层价值是:ViewModel 成为了可复用的中介者(或视为服务提供者),可被任意视图观察和复用;同时,一个视图使用多个 ViewModel 为其提供服务也成为自然。ViewModel 和 Presenter 相比,粒度更小、复用性更高。

这些改善之处,让 MVVM 迅速取代 MVP 成为主流。

4. MVI:单向闭环(3 根连线 + 严格单向流)

MVI 是最新的进化,它在 MVVM 的基础上,把数据流也彻底拉直:

  • 所有用户操作汇总为单一 Intent
  • 所有 UI 状态聚合为一个不可变的 State
  • 数据流形成严格的单向循环:用户操作 → Intent → ViewModel → Model → 新 State → View 渲染

从引用关系看,MVI 和 MVVM 都是 3 根连线。但 MVI 强制规定:任何状态变化都必须经过 ViewModel 处理,View 不得直接篡改数据。

这带来了巨大的工程红利:

  • 状态集中管理,可鸟瞰整个页面行为
  • 状态不可变,杜绝意外篡改
  • 行为完全可预测,易于调试和埋点
  • 支持时间旅行调试、统一日志等高级功能

然而 MVI 也有致命的实施门槛。 它对开发者的抽象能力要求极高。当思维混乱、缺乏拆分意识的程序员使用 MVI 时,就会掉入三个典型陷阱:

  1. Intent 爆炸:一个复杂页面定义出 200+ 个 Intent,命名又臭又长,职责重叠,反而比原来更难维护。
  2. God State:一个 State 对象塞进 30 个互不相关的字段,更新时牵一发动全身。
  3. 网状依赖:多个 Intent 相互调用,形成新的混乱调用链,让单向流名存实亡。

本该严谨的有限状态机,就这样被用成了"无限状态机"——这正是 MVI 被一部分人视为灾难的根源。


二、架构只是"术":它无法阻止你写出垃圾代码

我亲眼见过许多荒谬的项目:

  • 用着先进的 MVVM,却写出 5000 行的 ViewModel(架构管不到 ViewModel 内部的臃肿)
  • 严格遵循 Clean Architecture,却在 Domain 层塞满业务耦合(架构管不到 UseCase 之间的边界)
  • 坚持 MVI 单向流,却在一个 State 里混杂了轮播图、推荐列表和用户信息(架构管不到 State 的粒度)

糟糕的编程习惯制造出来的垃圾,不会因为换了一个架构就自动消失。我们只不过是把垃圾从 Activity 搬到了 Presenter,又从 Presenter 搬到了 ViewModel,再从 ViewModel 搬到了 UseCase。我们只是把垃圾从一个房间搬到了另一个房间,并没有真正把它清理掉。

就像同一段登录逻辑:

  • 在 MVC 中,它散落在 Activity 的各个角落
  • 重构到 MVP 后,它被完整地复制进 Presenter,却仍然是 300 行的过程式代码
  • 迁移到 MVVM 后,它又被塞进一个 LoginViewModel,里面的 login() 方法依然像一团乱麻
  • 再改成 MVI,它变成了一堆杂乱的 Intent 和 State,表面上单向,实际逻辑纠缠如初

架构是"术",它只解决了代码的"粗略分区",比如规定 View、ViewModel、Model 分别放在哪一层,但无法告诉你同一层的代码应该拆多细、怎么组织、怎么复用。而真正让代码变好的因素至少还包括:

  • 编程思想:分治、抽象、单一职责等基本原则,决定了我们如何看待和拆解问题。
  • 编码洁癖:对冗余代码、脏命名、越界逻辑的零容忍,保持代码库的长期健康。
  • 编程素养:写出可读、可测、可维护代码的习惯与意识,让协作不再痛苦。
  • 科学的实施方案:可落地的工具封装策略、治理流程、迭代机制,确保思想能真正被执行。

而这些也是一个优秀工程师应该具备的基础能力和素养。具备这些能力的工程师,不需要依赖某种"银弹架构",也能写出干净、健壮、易演化的代码。


相关阅读

Top comments (0)