第1章 Android 应用的基本构成
以统一TODO规格比较MVP、MVVM,并解释平台约束、历史问题、库与语言的影响
第1章 Android 应用的基本构成
本页依据PEAKS最终商品页、官方样章完整目录和书中指定样例仓库重构。正式书由日高正博、小西裕介、藤原聖、吉岡毅、今井智章合著,2018年1月31日发行,224页;本课程严格保留出版时的Android技术语境。
本页位于 第I部 アプリの設計を知る。 以统一TODO规格比较MVP、MVVM,并解释平台约束、历史问题、库与语言的影响。核心任务是把五屏TODO应用作为控制变量,从职责、依赖方向、生命周期与可测试性解释Android架构为何演进。先把结论写成可被反例推翻的预测,再阅读机制与案例。
学习目标
- 能解释“第1章 Android 应用的基本构成”全部正式目录节点,并画出角色、依赖方向、状态所有权和生命周期。
- 能比较至少两种设计选择,说明收益、代价、团队前提和不可采用的反例。
- 能设计旋转、后台、迟到回调、空数据或协作冲突实验,验证“TODO的新增、编辑、删除、本地保存和远端同步语义不随架构改变;改变的只能是职责分配与协作协议”。
- 能写出包含版本、代码快照、状态轨迹、测试结果、回退条件和责任人的交接记录。
从一个可证伪的问题开始
先预测:如果只更换类名或框架,而没有改变责任、依赖方向和状态所有者,只把类改名为ViewModel或Presenter而不改变依赖方向,会继续留下Fat Activity、生命周期泄漏和无法隔离测试的问题。把预测落实为同一输入下的两条运行轨迹,不要把“能编译”“页面能打开”当成架构正确。
本书的核心不是宣布唯一正确架构,而是建立讨论土台。项目规模、Android生命周期、既有代码、交付期限和团队结构都会改变最合适的选择。为此,本页始终保留业务控制变量,只修改一个设计因素,观察变更扩散、测试隔离、恢复行为和认知成本。
验收不变量是:TODO的新增、编辑、删除、本地保存和远端同步语义不随架构改变;改变的只能是职责分配与协作协议。若结论无法由代码快照、调用/状态轨迹、失败注入和团队交付事实共同支持,就只能记为待验证假设。
核心词汇与2018年边界
↡MVP是本页第1个核心概念;必须同时说明职责、依赖方向、生命周期、失败反例与可观察证据、↡MVVM是本页第2个核心概念;必须同时说明职责、依赖方向、生命周期、失败反例与可观察证据、↡Fat Activity是本页第3个核心概念;必须同时说明职责、依赖方向、生命周期、失败反例与可观察证据、↡ライフサイクル是本页第4个核心概念;必须同时说明职责、依赖方向、生命周期、失败反例与可观察证据、↡Android Architecture Components是本页第5个核心概念;必须同时说明职责、依赖方向、生命周期、失败反例与可观察证据
以上词汇都要回答五个问题:谁拥有状态、谁可以修改、Android生命周期如何影响它、失败从哪里传播、怎样证明恢复正确。Compose、Flow、Hilt、Navigation Compose以及后来的Jetpack最佳实践可作为迁移对照,但不能改写2018年正式目录的含义。
原书目录逐节点重构
第I部 アプリの設計を知る
该部标题是正式目录层级,不是装饰。它规定本页是在建立共同基础、读取真实案例,还是评估新组件。
1.1 議論の前提となるアプリケーションと仕様
固定新增、编辑、删除、列表、详情、统计和持久化行为,使架构比较只改变职责分配而不改变业务题目。 本节点不能只给结论:先预测正常轨迹,再注入旋转、后台、迟到回调、空数据或协作冲突中的一个变量,最后以TODO的新增、编辑、删除、本地保存和远端同步语义不随架构改变;改变的只能是职责分配与协作协议作为验收不变量。
本节要把“1.1 議論の前提となるアプリケーションと仕様”落实到一个可观察的协作协议:谁发起、谁拥有事实、谁只渲染、何时取消、失败后能否重试、团队如何独立修改。比较时保持业务样本与输入不变,只改变一个架构边界,并保存前后状态与调用轨迹。
1.2 アーキテクチャの選択
先列约束和质量目标,再比较依赖方向、生命周期、测试替身、学习成本与迁移成本;不能从模式名称反推适用性。 本节点不能只给结论:先预测正常轨迹,再注入旋转、后台、迟到回调、空数据或协作冲突中的一个变量,最后以TODO的新增、编辑、删除、本地保存和远端同步语义不随架构改变;改变的只能是职责分配与协作协议作为验收不变量。
本节要把“1.2 アーキテクチャの選択”落实到一个可观察的协作协议:谁发起、谁拥有事实、谁只渲染、何时取消、失败后能否重试、团队如何独立修改。比较时保持业务样本与输入不变,只改变一个架构边界,并保存前后状态与调用轨迹。
1.3 Model-View-Presenter
Presenter接收用户意图并调用数据边界,再通过窄View契约显式渲染;测试应验证调用次序、空态、错误态和分离后的迟到回调。 本节点不能只给结论:先预测正常轨迹,再注入旋转、后台、迟到回调、空数据或协作冲突中的一个变量,最后以TODO的新增、编辑、删除、本地保存和远端同步语义不随架构改变;改变的只能是职责分配与协作协议作为验收不变量。
本节要把“1.3 Model-View-Presenter”落实到一个可观察的协作协议:谁发起、谁拥有事实、谁只渲染、何时取消、失败后能否重试、团队如何独立修改。比较时保持业务样本与输入不变,只改变一个架构边界,并保存前后状态与调用轨迹。
1.4 Model-View-ViewModel
ViewModel暴露可观察页面状态,不持有具体View;View通过绑定或观察更新,瞬时导航与持久状态必须分开建模。 本节点不能只给结论:先预测正常轨迹,再注入旋转、后台、迟到回调、空数据或协作冲突中的一个变量,最后以TODO的新增、编辑、删除、本地保存和远端同步语义不随架构改变;改变的只能是职责分配与协作协议作为验收不变量。
本节要把“1.4 Model-View-ViewModel”落实到一个可观察的协作协议:谁发起、谁拥有事实、谁只渲染、何时取消、失败后能否重试、团队如何独立修改。比较时保持业务样本与输入不变,只改变一个架构边界,并保存前后状态与调用轨迹。
1.4.1 データバインディング
布局声明状态到控件属性的映射,减少命令式查找与赋值;验收要覆盖空值、解绑、重建和重复观察。 本节点不能只给结论:先预测正常轨迹,再注入旋转、后台、迟到回调、空数据或协作冲突中的一个变量,最后以TODO的新增、编辑、删除、本地保存和远端同步语义不随架构改变;改变的只能是职责分配与协作协议作为验收不变量。
核查点: 记录该节点的主体、依赖、状态、生命周期、异常出口和一条失败证据;若只有类图而没有运行轨迹,本节点不算掌握。
1.4.2 MVVMのベースの考え方:Presentation Model
ViewModel暴露可观察页面状态,不持有具体View;View通过绑定或观察更新,瞬时导航与持久状态必须分开建模。 本节点不能只给结论:先预测正常轨迹,再注入旋转、后台、迟到回调、空数据或协作冲突中的一个变量,最后以TODO的新增、编辑、删除、本地保存和远端同步语义不随架构改变;改变的只能是职责分配与协作协议作为验收不变量。
核查点: 记录该节点的主体、依赖、状态、生命周期、异常出口和一条失败证据;若只有类图而没有运行轨迹,本节点不算掌握。
1.5 プラットフォームの制約と複雑性
把“プラットフォームの制約と複雑性”放回把五屏TODO应用作为控制变量,从职责、依赖方向、生命周期与可测试性解释Android架构为何演进这条因果链,明确输入、状态所有者、输出和停止条件。 本节点不能只给结论:先预测正常轨迹,再注入旋转、后台、迟到回调、空数据或协作冲突中的一个变量,最后以TODO的新增、编辑、删除、本地保存和远端同步语义不随架构改变;改变的只能是职责分配与协作协议作为验收不变量。
本节要把“1.5 プラットフォームの制約と複雑性”落实到一个可观察的协作协议:谁发起、谁拥有事实、谁只渲染、何时取消、失败后能否重试、团队如何独立修改。比较时保持业务样本与输入不变,只改变一个架构边界,并保存前后状态与调用轨迹。
1.6 設計の歴史
把“設計の歴史”放回把五屏TODO应用作为控制变量,从职责、依赖方向、生命周期与可测试性解释Android架构为何演进这条因果链,明确输入、状态所有者、输出和停止条件。 本节点不能只给结论:先预测正常轨迹,再注入旋转、后台、迟到回调、空数据或协作冲突中的一个变量,最后以TODO的新增、编辑、删除、本地保存和远端同步语义不随架构改变;改变的只能是职责分配与协作协议作为验收不变量。
本节要把“1.6 設計の歴史”落实到一个可观察的协作协议:谁发起、谁拥有事实、谁只渲染、何时取消、失败后能否重试、团队如何独立修改。比较时保持业务样本与输入不变,只改变一个架构边界,并保存前后状态与调用轨迹。
1.6.1 Fat Activity問題
Android组件只负责装配、生命周期桥接、渲染和转发意图,业务判断进入可替换的Presenter、ViewModel或Store。 本节点不能只给结论:先预测正常轨迹,再注入旋转、后台、迟到回调、空数据或协作冲突中的一个变量,最后以TODO的新增、编辑、删除、本地保存和远端同步语义不随架构改变;改变的只能是职责分配与协作协议作为验收不变量。
核查点: 记录该节点的主体、依赖、状态、生命周期、异常出口和一条失败证据;若只有类图而没有运行轨迹,本节点不算掌握。
1.6.2 ライフサイクルの複雑化
逐一记录create、start、stop、配置变更和最终destroy,确认订阅、缓存、实例复用与释放都发生在正确边界。 本节点不能只给结论:先预测正常轨迹,再注入旋转、后台、迟到回调、空数据或协作冲突中的一个变量,最后以TODO的新增、编辑、删除、本地保存和远端同步语义不随架构改变;改变的只能是职责分配与协作协议作为验收不变量。
核查点: 记录该节点的主体、依赖、状态、生命周期、异常出口和一条失败证据;若只有类图而没有运行轨迹,本节点不算掌握。
1.6.3 バージョン差分
兼容层缓冲平台版本差异,但API可用性和实际设备行为仍需矩阵验证,不能只依赖编译通过。 本节点不能只给结论:先预测正常轨迹,再注入旋转、后台、迟到回调、空数据或协作冲突中的一个变量,最后以TODO的新增、编辑、删除、本地保存和远端同步语义不随架构改变;改变的只能是职责分配与协作协议作为验收不变量。
核查点: 记录该节点的主体、依赖、状态、生命周期、异常出口和一条失败证据;若只有类图而没有运行轨迹,本节点不算掌握。
1.6.4 非同期処理とバックグラウンド実行
流式组合能显式表达异步链,但线程、取消、重试、错误和订阅释放仍需由架构边界负责。 本节点不能只给结论:先预测正常轨迹,再注入旋转、后台、迟到回调、空数据或协作冲突中的一个变量,最后以TODO的新增、编辑、删除、本地保存和远端同步语义不随架构改变;改变的只能是职责分配与协作协议作为验收不变量。
核查点: 记录该节点的主体、依赖、状态、生命周期、异常出口和一条失败证据;若只有类图而没有运行轨迹,本节点不算掌握。
1.6.5 チーム開発
把“チーム開発”放回把五屏TODO应用作为控制变量,从职责、依赖方向、生命周期与可测试性解释Android架构为何演进这条因果链,明确输入、状态所有者、输出和停止条件。 本节点不能只给结论:先预测正常轨迹,再注入旋转、后台、迟到回调、空数据或协作冲突中的一个变量,最后以TODO的新增、编辑、删除、本地保存和远端同步语义不随架构改变;改变的只能是职责分配与协作协议作为验收不变量。
核查点: 记录该节点的主体、依赖、状态、生命周期、异常出口和一条失败证据;若只有类图而没有运行轨迹,本节点不算掌握。
1.7 ライブラリの台頭
把“ライブラリの台頭”放回把五屏TODO应用作为控制变量,从职责、依赖方向、生命周期与可测试性解释Android架构为何演进这条因果链,明确输入、状态所有者、输出和停止条件。 本节点不能只给结论:先预测正常轨迹,再注入旋转、后台、迟到回调、空数据或协作冲突中的一个变量,最后以TODO的新增、编辑、删除、本地保存和远端同步语义不随架构改变;改变的只能是职责分配与协作协议作为验收不变量。
本节要把“1.7 ライブラリの台頭”落实到一个可观察的协作协议:谁发起、谁拥有事实、谁只渲染、何时取消、失败后能否重试、团队如何独立修改。比较时保持业务样本与输入不变,只改变一个架构边界,并保存前后状态与调用轨迹。
1.7.1 Android Architecture Components
把“Android Architecture Components”放回把五屏TODO应用作为控制变量,从职责、依赖方向、生命周期与可测试性解释Android架构为何演进这条因果链,明确输入、状态所有者、输出和停止条件。 本节点不能只给结论:先预测正常轨迹,再注入旋转、后台、迟到回调、空数据或协作冲突中的一个变量,最后以TODO的新增、编辑、删除、本地保存和远端同步语义不随架构改变;改变的只能是职责分配与协作协议作为验收不变量。
核查点: 记录该节点的主体、依赖、状态、生命周期、异常出口和一条失败证据;若只有类图而没有运行轨迹,本节点不算掌握。
1.7.2 Android Support Library
兼容层缓冲平台版本差异,但API可用性和实际设备行为仍需矩阵验证,不能只依赖编译通过。 本节点不能只给结论:先预测正常轨迹,再注入旋转、后台、迟到回调、空数据或协作冲突中的一个变量,最后以TODO的新增、编辑、删除、本地保存和远端同步语义不随架构改变;改变的只能是职责分配与协作协议作为验收不变量。
核查点: 记录该节点的主体、依赖、状态、生命周期、异常出口和一条失败证据;若只有类图而没有运行轨迹,本节点不算掌握。
1.7.3 Dagger 2
依赖注入建立组合根和作用域,价值在于替换、生命周期对齐与依赖可见,而不是减少new关键字。 本节点不能只给结论:先预测正常轨迹,再注入旋转、后台、迟到回调、空数据或协作冲突中的一个变量,最后以TODO的新增、编辑、删除、本地保存和远端同步语义不随架构改变;改变的只能是职责分配与协作协议作为验收不变量。
核查点: 记录该节点的主体、依赖、状态、生命周期、异常出口和一条失败证据;若只有类图而没有运行轨迹,本节点不算掌握。
1.7.4 Gson
网络和序列化库分别承担传输、接口映射和数据转换;超时、HTTP错误、字段演化与取消不能被统一成一个成功/失败布尔值。 本节点不能只给结论:先预测正常轨迹,再注入旋转、后台、迟到回调、空数据或协作冲突中的一个变量,最后以TODO的新增、编辑、删除、本地保存和远端同步语义不随架构改变;改变的只能是职责分配与协作协议作为验收不变量。
核查点: 记录该节点的主体、依赖、状态、生命周期、异常出口和一条失败证据;若只有类图而没有运行轨迹,本节点不算掌握。
1.7.5 OkHttp
网络和序列化库分别承担传输、接口映射和数据转换;超时、HTTP错误、字段演化与取消不能被统一成一个成功/失败布尔值。 本节点不能只给结论:先预测正常轨迹,再注入旋转、后台、迟到回调、空数据或协作冲突中的一个变量,最后以TODO的新增、编辑、删除、本地保存和远端同步语义不随架构改变;改变的只能是职责分配与协作协议作为验收不变量。
核查点: 记录该节点的主体、依赖、状态、生命周期、异常出口和一条失败证据;若只有类图而没有运行轨迹,本节点不算掌握。
1.7.6 PermissionsDispatcher
所有意图和结果都写成Action,经Dispatcher进入Store计算新状态,再由View观察;日志应能从Action重建状态变化。 本节点不能只给结论:先预测正常轨迹,再注入旋转、后台、迟到回调、空数据或协作冲突中的一个变量,最后以TODO的新增、编辑、删除、本地保存和远端同步语义不随架构改变;改变的只能是职责分配与协作协议作为验收不变量。
核查点: 记录该节点的主体、依赖、状态、生命周期、异常出口和一条失败证据;若只有类图而没有运行轨迹,本节点不算掌握。
1.7.7 Retrofit 2
网络和序列化库分别承担传输、接口映射和数据转换;超时、HTTP错误、字段演化与取消不能被统一成一个成功/失败布尔值。 本节点不能只给结论:先预测正常轨迹,再注入旋转、后台、迟到回调、空数据或协作冲突中的一个变量,最后以TODO的新增、编辑、删除、本地保存和远端同步语义不随架构改变;改变的只能是职责分配与协作协议作为验收不变量。
核查点: 记录该节点的主体、依赖、状态、生命周期、异常出口和一条失败证据;若只有类图而没有运行轨迹,本节点不算掌握。
1.7.8 RxJava 2
流式组合能显式表达异步链,但线程、取消、重试、错误和订阅释放仍需由架构边界负责。 本节点不能只给结论:先预测正常轨迹,再注入旋转、后台、迟到回调、空数据或协作冲突中的一个变量,最后以TODO的新增、编辑、删除、本地保存和远端同步语义不随架构改变;改变的只能是职责分配与协作协议作为验收不变量。
核查点: 记录该节点的主体、依赖、状态、生命周期、异常出口和一条失败证据;若只有类图而没有运行轨迹,本节点不算掌握。
1.8 プログラミング言語の発展
语言能力会改变空值、函数、不可变性和样板成本,但最终成书未保留计划中的Kotlin正式章,本节只能说明语言影响的背景。 本节点不能只给结论:先预测正常轨迹,再注入旋转、后台、迟到回调、空数据或协作冲突中的一个变量,最后以TODO的新增、编辑、删除、本地保存和远端同步语义不随架构改变;改变的只能是职责分配与协作协议作为验收不变量。
本节要把“1.8 プログラミング言語の発展”落实到一个可观察的协作协议:谁发起、谁拥有事实、谁只渲染、何时取消、失败后能否重试、团队如何独立修改。比较时保持业务样本与输入不变,只改变一个架构边界,并保存前后状态与调用轨迹。
完整节点清单与覆盖门
本页承担下列23个目录或检索节点;正文、图解、实验和题目必须都能反向定位这些节点:
- 1.1 議論の前提となるアプリケーションと仕様
- 1.2 アーキテクチャの選択
- 1.3 Model-View-Presenter
- 1.4 Model-View-ViewModel
- 1.4.1 データバインディング
- 1.4.2 MVVMのベースの考え方:Presentation Model
- 1.5 プラットフォームの制約と複雑性
- 1.6 設計の歴史
- 1.6.1 Fat Activity問題
- 1.6.2 ライフサイクルの複雑化
- 1.6.3 バージョン差分
- 1.6.4 非同期処理とバックグラウンド実行
- 1.6.5 チーム開発
- 1.7 ライブラリの台頭
- 1.7.1 Android Architecture Components
- 1.7.2 Android Support Library
- 1.7.3 Dagger 2
- 1.7.4 Gson
- 1.7.5 OkHttp
- 1.7.6 PermissionsDispatcher
- 1.7.7 Retrofit 2
- 1.7.8 RxJava 2
- 1.8 プログラミング言語の発展
分步推导:从结构到运行事实
先画责任与依赖
固定业务输入,标明Android组件、Presenter/ViewModel/Store、数据边界与团队所有者。箭头表示调用或数据流,不能只画文件夹。
可复现实验与记录格式
以下三个片段分别固定版本/结构、运行轨迹和证据表。它们是实验协议,不是要求照抄的生产模板:
interface TodoView { void render(TodoUiState state); }
interface TodoPresenter { void load(); void add(String title); }create -> start -> rotate -> recreate -> restore -> stop -> backgroundsame TODO specification | MVP trace | MVVM trace | observable difference动手试:用同一TODO或章节案例分别运行正常、旋转/重建、后台、迟到成功、迟到失败五条路径。每条路径记录输入、对象实例、线程/调度、状态前后值、UI结果和释放点。若是团队案例,再增加变更文件数、评审往返和回退耗时。
独立证据门
证据包至少包含:正式目录映射、来源URL、出版前代码提交、角色与依赖图、生命周期轨迹、一个单变量失败实验、测试输出、业务/团队指标、停止条件、回退步骤和复核人。图和代码必须使用相同角色命名,否则无法交叉验证。
练习
练习
问题 1:为什么本页必须以同一业务规格作为控制变量?
问题 2:怎样构造“只把类改名为ViewModel或Presenter而不改变依赖方向,会继续留下Fat Activity、生命周期泄漏和无法隔离测试的问题”的最小反例?
问题 3:何时可以认为“第1章 Android 应用的基本构成”已完成独立交接?
本章回顾
“第1章 Android 应用的基本构成”的核心不是记忆名词,而是把五屏TODO应用作为控制变量,从职责、依赖方向、生命周期与可测试性解释Android架构为何演进。最终结论必须同时经受平台生命周期、失败路径、既有代码和团队协作四类约束;只把类改名为ViewModel或Presenter而不改变依赖方向,会继续留下Fat Activity、生命周期泄漏和无法隔离测试的问题就是本页必须保留的反证边界。
名词解释
本章出现的专业名词,用大白话再讲一遍。
- MVP
MVP用于解释“把五屏TODO应用作为控制变量,从职责、依赖方向、生命周期与可测试性解释Android架构为何演进”。掌握标准不是记住名称,而是能画出责任与状态轨迹、构造单变量反例,并用“TODO的新增、编辑、删除、本地保存和远端同步语义不随架构改变;改变的只能是职责分配与协作协议”完成验收。
- MVVM
MVVM用于解释“把五屏TODO应用作为控制变量,从职责、依赖方向、生命周期与可测试性解释Android架构为何演进”。掌握标准不是记住名称,而是能画出责任与状态轨迹、构造单变量反例,并用“TODO的新增、编辑、删除、本地保存和远端同步语义不随架构改变;改变的只能是职责分配与协作协议”完成验收。
- Fat Activity
Fat Activity用于解释“把五屏TODO应用作为控制变量,从职责、依赖方向、生命周期与可测试性解释Android架构为何演进”。掌握标准不是记住名称,而是能画出责任与状态轨迹、构造单变量反例,并用“TODO的新增、编辑、删除、本地保存和远端同步语义不随架构改变;改变的只能是职责分配与协作协议”完成验收。
- ライフサイクル
ライフサイクル用于解释“把五屏TODO应用作为控制变量,从职责、依赖方向、生命周期与可测试性解释Android架构为何演进”。掌握标准不是记住名称,而是能画出责任与状态轨迹、构造单变量反例,并用“TODO的新增、编辑、删除、本地保存和远端同步语义不随架构改变;改变的只能是职责分配与协作协议”完成验收。
- Android Architecture Components
Android Architecture Components用于解释“把五屏TODO应用作为控制变量,从职责、依赖方向、生命周期与可测试性解释Android架构为何演进”。掌握标准不是记住名称,而是能画出责任与状态轨迹、构造单变量反例,并用“TODO的新增、编辑、删除、本地保存和远端同步语义不随架构改变;改变的只能是职责分配与协作协议”完成验收。