Now in Android:它不是最佳实践,而是大型 Android 工程实践的展示

Now in Android:它不是最佳实践,而是大型 Android 工程实践的展示

核心观点

Now in Android(NIA)经常被批评为"过度设计",但这种评价只有在忽略其目标的情况下才成立。

NIA 的价值并不在于提供一个适用于所有 Android 项目的模板,而在于展示 Google 对大型 Android 应用工程化的理解。因此,对 NIA 的评价必须结合项目规模和团队背景。

NIA 解决的问题是什么?

阅读 NIA 的官方文档后可以发现,它关注的是以下几个目标:

  • 支持多人并行开发;
  • 降低大型项目的构建成本;
  • 提高代码的可测试性;
  • 演示 Jetpack 官方推荐实践;
  • 提供性能优化与持续集成的示例。

这些目标都不是"小型应用如何快速开发"。

因此,NIA 的设计天然偏向大型团队和长期维护的场景。

为什么会被认为"过度设计"?

1. 模块拆分过细

NIA 将应用拆分为大量模块,例如:

  • feature:me
  • core:ui
  • core:data
  • core:database
  • core:datastore等。

对于只有几名开发者的项目而言,这种拆分会带来额外成本:

  • Gradle 配置复杂;
  • 新成员上手困难;
  • 查找代码成本增加;
  • 重构需要跨多个模块协调。

模块化本身并不是问题,问题在于模块化程度是否与项目规模匹配。

2. 小功能采用完整架构链路

在 NIA 中,即使是简单的数据修改,也可能经过:
#mermaid-svg-vTEzBQ7dDVrnVFfT{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-vTEzBQ7dDVrnVFfT .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-vTEzBQ7dDVrnVFfT .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-vTEzBQ7dDVrnVFfT .error-icon{fill:#552222;}#mermaid-svg-vTEzBQ7dDVrnVFfT .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-vTEzBQ7dDVrnVFfT .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-vTEzBQ7dDVrnVFfT .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-vTEzBQ7dDVrnVFfT .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-vTEzBQ7dDVrnVFfT .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-vTEzBQ7dDVrnVFfT .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-vTEzBQ7dDVrnVFfT .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-vTEzBQ7dDVrnVFfT .marker{fill:#333333;stroke:#333333;}#mermaid-svg-vTEzBQ7dDVrnVFfT .marker.cross{stroke:#333333;}#mermaid-svg-vTEzBQ7dDVrnVFfT svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-vTEzBQ7dDVrnVFfT p{margin:0;}#mermaid-svg-vTEzBQ7dDVrnVFfT .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-vTEzBQ7dDVrnVFfT .cluster-label text{fill:#333;}#mermaid-svg-vTEzBQ7dDVrnVFfT .cluster-label span{color:#333;}#mermaid-svg-vTEzBQ7dDVrnVFfT .cluster-label span p{background-color:transparent;}#mermaid-svg-vTEzBQ7dDVrnVFfT .label text,#mermaid-svg-vTEzBQ7dDVrnVFfT span{fill:#333;color:#333;}#mermaid-svg-vTEzBQ7dDVrnVFfT .node rect,#mermaid-svg-vTEzBQ7dDVrnVFfT .node circle,#mermaid-svg-vTEzBQ7dDVrnVFfT .node ellipse,#mermaid-svg-vTEzBQ7dDVrnVFfT .node polygon,#mermaid-svg-vTEzBQ7dDVrnVFfT .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-vTEzBQ7dDVrnVFfT .rough-node .label text,#mermaid-svg-vTEzBQ7dDVrnVFfT .node .label text,#mermaid-svg-vTEzBQ7dDVrnVFfT .image-shape .label,#mermaid-svg-vTEzBQ7dDVrnVFfT .icon-shape .label{text-anchor:middle;}#mermaid-svg-vTEzBQ7dDVrnVFfT .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-vTEzBQ7dDVrnVFfT .rough-node .label,#mermaid-svg-vTEzBQ7dDVrnVFfT .node .label,#mermaid-svg-vTEzBQ7dDVrnVFfT .image-shape .label,#mermaid-svg-vTEzBQ7dDVrnVFfT .icon-shape .label{text-align:center;}#mermaid-svg-vTEzBQ7dDVrnVFfT .node.clickable{cursor:pointer;}#mermaid-svg-vTEzBQ7dDVrnVFfT .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-vTEzBQ7dDVrnVFfT .arrowheadPath{fill:#333333;}#mermaid-svg-vTEzBQ7dDVrnVFfT .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-vTEzBQ7dDVrnVFfT .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-vTEzBQ7dDVrnVFfT .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-vTEzBQ7dDVrnVFfT .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-vTEzBQ7dDVrnVFfT .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-vTEzBQ7dDVrnVFfT .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-vTEzBQ7dDVrnVFfT .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-vTEzBQ7dDVrnVFfT .cluster text{fill:#333;}#mermaid-svg-vTEzBQ7dDVrnVFfT .cluster span{color:#333;}#mermaid-svg-vTEzBQ7dDVrnVFfT div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-vTEzBQ7dDVrnVFfT .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-vTEzBQ7dDVrnVFfT rect.text{fill:none;stroke-width:0;}#mermaid-svg-vTEzBQ7dDVrnVFfT .icon-shape,#mermaid-svg-vTEzBQ7dDVrnVFfT .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-vTEzBQ7dDVrnVFfT .icon-shape p,#mermaid-svg-vTEzBQ7dDVrnVFfT .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-vTEzBQ7dDVrnVFfT .icon-shape .label rect,#mermaid-svg-vTEzBQ7dDVrnVFfT .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-vTEzBQ7dDVrnVFfT .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-vTEzBQ7dDVrnVFfT .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-vTEzBQ7dDVrnVFfT :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} UI
ViewModel
Repository
Local DataSource
Remote DataSource
Database
API

Repository 的价值并不在于"多了一层",而在于屏蔽数据来源的变化;但如果项目永远只有一种数据来源,这层抽象就可能成为过度设计。

这种设计强调职责分离和可测试性,但对于需求变化频繁、生命周期较短的项目而言,会增加实现成本。

因此,很多开发者会产生一种感受:

"为了实现一个简单功能,却引入了远超需求的复杂度。"

3. 性能与测试设施齐全

NIA 包含:

  • Macrobenchmark;
  • Baseline Profile;
  • 自动化测试;
  • CI 流程;
  • Benchmark 模块。

对于大多数中小团队来说,这些设施并不是当前阶段的瓶颈。

但对于拥有数百万用户的大型应用而言,启动时间减少 100ms 就可能带来显著收益。

NIA 的真正定位

NIA 更像是一个"参考架构",而不是"项目脚手架"。

它回答的问题是:

"如果从零开始构建一个现代 Android 大型应用,Google 会如何组织它?"

而不是:

"如果我要在两个月内交付一个 App,我应该怎么写?"

将这两类问题混淆,是很多争论产生的原因。

对 NIA 的评价应该基于项目规模

小型项目(1~5人)

适合借鉴:

  • Compose;
  • ViewModel;
  • Repository;
  • Hilt;
  • 少量模块化。

不适合照搬:

  • 复杂模块拆分;
  • Benchmark 基础设施;
  • 完整测试矩阵。

中大型项目(10人以上)

NIA 的很多设计开始体现价值:

  • 降低多人协作冲突;
  • 支持独立模块开发;
  • 提高测试能力;
  • 控制构建时间;
  • 保障长期可维护性。

一个有用的类比

NIA 与 Kubernetes 有相似之处。

对于个人博客而言,Kubernetes 是过度设计。

对于拥有数百个微服务的企业系统而言,Kubernetes 是必要基础设施。

NIA 也是如此:

  • 对 Todo App 来说,它可能太重;
  • 对维护五年的大型 Android 应用来说,它可能正合适。

复杂度本身不是问题。

不匹配的复杂度才是问题。

我的结论

Now in Android 不是 Android 开发的"标准答案"。

它更像是一份展示大型工程实践的样板间。

学习 NIA 的正确方式不是复制,而是理解:

  • 哪些复杂度是在解决真实问题;
  • 哪些复杂度在当前阶段并不需要;
  • 哪些设计可以随着项目成长逐步引入。

好的架构不是"最先进"的架构,而是"刚好足够"的架构。

因此,与其问:

"Now in Android 是否过度设计?"

不如问:

"我的项目是否已经遇到了 NIA 想要解决的问题?"

如果答案是否定的,那么简化就是一种更好的设计。

相关推荐
成都大菠萝1 天前
Android Car CarProperty 车辆信号链路
android
敲代码的鱼1 天前
PDF 预览与签名批注写回 支持安卓 iOS 鸿蒙 UTS插件
android·前端·ios
时光足迹1 天前
uni-app 视频通话实战:康复师与患者视频问诊的 6 个致命 Bug 与解决方案
android·ios·uni-app
Coffeeee1 天前
闲聊几句,Android老哥们,你们多久没做技改需求了
android·程序员·代码规范
萝卜er1 天前
Fragment 生命周期与状态恢复-《Android深水区(四)》
android
萝卜er1 天前
Intent 显式、隐式与 PendingIntent-《Android深水区(五)》
android
Kapaseker1 天前
一文吃透 Kotlin 集合操作符
android·kotlin
三少爷的鞋1 天前
Main-safe:现代Android 架构真正的分水岭
android
沐怡旸2 天前
深入解析 Android Performance Analyzer (APA) 底层架构与技术原理
android
李斯维2 天前
从历史的角度看 Android 软件架构
android·架构·android jetpack