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 想要解决的问题?"

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

相关推荐
故渊at1 小时前
第三板块:Android 图形渲染与窗口体系 | 第十三篇:SurfaceFlinger 与 VSYNC 信号机制
android·图形渲染·surfaceflinger·帧率·窗口体系
Che2n3JigW2 小时前
Now in Android Feature 模块分析:一个功能是如何被组织起来的?
android·udf·architecture·now in android·modularization·feature module
Che2n3JigW2 小时前
Now in Android 项目结构分析:这个 App 是如何搭建起来的?
android·architecture·now in android·modularization·structure
恋猫de小郭2 小时前
flutter_agent_lens 用 MCP 服务,将 Flutter DevTools 暴露给 AI
android·前端·flutter
AI玫瑰助手2 小时前
Python函数:内置函数(len/max/min/sorted等)详解
android·开发语言·python
Kapaseker2 小时前
Kotlin 集合:只读不等于不可变
android·kotlin
风华圆舞2 小时前
一个 Flutter 项目同时保留 Android、iOS、HarmonyOS 支持的实践
android·flutter·ios
顾林海2 小时前
Android来时路:Android 是什么
android
2501_915921432 小时前
uni-app 上架 iOS 的完整流程(无需依赖 Mac)
android·macos·ios·小程序·uni-app·iphone·webview