Android 官方现代 App 架构指南(android 应用架构)

作者: madroid

回顾

根据 App 行为的不同,我们对其进行分离/分层并确定其职责,每层之间的通讯交互采用响应式方式。

App 有三层结构,分别为 UI LayerDomain LayerData Layer,其依赖关系是单向的,上层可以依赖下层,下层却不能反过来依赖上层。大致如下,其中 Domain Layer 是可选层:

Android 官方现代 App 架构指南(android 应用架构)

△ App Arch Layer Design

每层的主要职责分别为:

1、UI Layer: 使用 UI 元素展示 App 中数据

    • 将底层数据处理成容易被 UI elements 使用的 Uistate 数据;
    • 根据 UiState 绘制对应的 UI elements
    • 响应用户的操作事件,根据需求对其进行分发;

2、Domain Layer: 封装通用的业务逻辑

    • 封装复杂的业务逻辑,避免出现大型类;
    • 封装多 ViewModel 通用的业务逻辑,避免代码重复;

3、Data Layer: 封装统一的数据来源,提供单一可信来源

    • 定义不同的 DataSource 来封装 Framework 及三方 SDK 的 API;
    • 定义 Repository 来整合相同业务的不同数据类型的 DataSource

每层依赖关系是单向的,UI Layer 可以依赖 Domain Layer,但是 Domain Layer 却不能依赖 UI Layer。这种依赖方式可以使用简单的函数传递依赖事件,但是却不能处理结果的回调,即 UiState 的更新。想要处理结果的回调每层之间就可以采用数据驱动/响应式的方式来交互了。这种方式也被称为是单向数据流的方式,即 UI 事件从 UI 层流向数据层,UiState 从数据层流向 UI 层。

Android 官方现代 App 架构指南(android 应用架构)

关于 UI LayerDomain LayerData Layer 中更多详细内容可以查看官方文档应用架构指南:

https://developer.android.google.cn/jetpack/guide

与 MVI 的关系?

MVI 的全称是 Model-View-Intent,这里的 Intent 并不是指 Android 中的 Intent 类,而是表示一种意图,可以简单理解为对用户 Event 的一种抽象。其交互图大致如下:

Android 官方现代 App 架构指南(android 应用架构)

MVI 并不像 MVCMVPMVVM 一样,不论是 Controller、Presenter 还是 ViewModel 都是 View 与 Model 之间的桥接类,负责这两者之间的通信与交互 (虽然 MVC 可以跨过 Controller 直接进行交互)。而 Intent 并没有类似的职责,仅仅是约束了 View 的事件通过类似枚举的方式定义,这种方式更像是前端框架中的 Flux 或者是 Redux,更多内容可以查看 Reclaim the reactivity of your state management, say no to imperative MVI,实现 MVI 的主流框架有: OrbitMavericksUniflow-ktMobius

  • Reclaim the reActivity of your state management, say no to imperative MVI

https://zhuinden.medium.com/reclaim-the-reactivity-of-your-state-management-say-no-to-imperative-mvi-3b23ca6b8537

  • Orbit

https://github.com/orbit-mvi/orbit-mvi/blob/06e9f759a87e7192767baeebc682fc92369a7eff/orbit-core/src/commonMain/kotlin/org/orbitmvi/orbit/internal/RealContainer.kt#L74-L75

  • Mavericks

https://github.com/airbnb/mavericks/blob/e8a631a19fc1b044da3ddff358712e129dc487a6/mvrx/src/main/kotlin/com/airbnb/mvrx/CoroutinesStateStore.kt#L57-L59

  • Uniflow-kt

https://github.com/uniflow-kt/uniflow-kt/blob/a1fdbeb733a0b550a162227be3b1e03d03197023/uniflow-core/src/main/kotlin/IO/uniflow/core/flow/ActionReducer.kt#L28-L32

  • Mobius

https://github.com/spotify/mobius

有的 MVI 在实现还需要借助 ViewModel,仅仅是把 View 的事件定义成的对应的密封类。目的仅仅是为了强制实现单向数据流的方式,根据之前介绍实现单向数据流的方式还是比较简单的,上层只能依赖下层实现,下层的处理结果通过 LiveData、Flow 方式更新。

那再来聊一下 MVCMVPMVVM 与 Android 官方的推荐的 MAD Arch 之间的关系。其实经常提到的 MVVM 与 Android 官方的架构还是有本质区别的。MVX (对 MVC、MVP、MVVM 的统称) 的架构方式对 Model 这一层提到的非常少,留下的印象可能就是除了 VX 之外剩下的就是 Model 的部分。但是这部分在整个 App 的架构中也是非常重要的。我们还是有大量的业务逻辑是在 Model 层处理的。

Android 官方现代 App 架构指南(android 应用架构)

而 Android 官方的架构中却包含了这部分的描述,新增了 Data LayerDomain Layer。所以总结下来就是 MVX 处理的仅仅是 UI Layer 中的问题,描述的是状态管理的部分;官方文档中描述的确是整个 App 的架构,是一种包含的关系。

如何处理线程

无论是在哪一层都要确保其在主线程安全的,即在主线程调用不会阻塞主线程或者是抛出异常。那应该是在哪一层进行处理呐?其可选项有 ViewModel、UseCase、Repository、DataSource,只要在任何一层处理耗时操作都可以确保其是主线程安全的。这里建议采用 "就近原则",即谁产生数据谁就保持数据的安全性。

Data Layer 中 DataSource 是 "产生" 数据的地方,在这里直接切换到对应的子线程是可以的,代码大致如下:

class NewsRemoteDataSource( private val newsApi: NewsApi, private val ioDispatcher: CoroutineDispatcher) { /** * 在 IO 线程中,获取网络数据,在主线程调用是安全的 */ suspend fun fetchLatestNews(): List<ArticleHeadline> = withContext(ioDispatcher) { // 将耗时操作移动到 IO 线程中 newsApi.fetchLatestNews() }}

如果 Repository 中需要整合很多的 DataSource 中的数据,在 Repository 中切换到对应的子线程也是可以的,这样可以减少频繁的线程调度。

同时也需要考虑响应业务的生命周期情况,如果当前业务跟随这页面进行的,那么使用 viewModelScope 或者是 lifecycleScope 即可;如果其业务是跟随 App 的什么周期的,那么则需要使用整个 App 生命周期的 CoroutineScope;如果在 App 被终止后,仍然希望可以执行任务,那么可以考虑使用 WorkManager:

https://developer.android.google.cn/topic/libraries/architecture/workmanager

如何处理实体类 (Entity)?

各层之间的 Entity 根据其职责定义会有所不同,可以根据具体的使用场景自定义 Entity。如云端返回的 Entity 与数据库需要存储的 Entity 可能并不相同,使用相同的 Entity 会导致代码的可维护性下降,而且没有必要暴露过多的细节。如下:

@Entity(tableName = "user")data class RemoteUser( @PrimaryKey @SerializedName("user_id") val userId: String, val username: String, @Ignore val token: String, @Ignore val inventory: RemoteInventory, @Ignore val profile: RemoteProfile,)

这种场景下,我们就可以针对云端返回数据与数据库存储数据分别定义不同的 Entity,如下:

// 云端数据 Entitydata class RemoteUser( @SerializedName("user_id") val userId: String, val username: String, val token: String, val inventory: RemoteInventory, val profile: RemoteProfile,)// 数据库 Entity@Entity(tableName = "user")data class UserEntity( @PrimaryKey val userId: String, val username: String,)

对于不同页面直接传递数据的场景 (Intent),建议定义单独的 Entity,因为传递数据的大小是有限的。定义大致如下:

@Parcelizedata class Inventory( val id: UUID, val type: String): Parcelable

对于 UI Layer 中的实体定义,要根据其业务类型进行细分,切记不要将一页面中的所有的 UiState 都定义在同一个 Entity 中。因为汇总型的定义在相关字段的更新频率不一致的时候会导致频繁的 UI element 重复绘制,同时不可变的 Entity 的字段增加也会导致不必要的内存开销。如果一个 UiState 中有超过 5 个状态,那就需要回过来看下 UiState 是否可以进行拆分了。

UiState 中经常遇到的一个场景就是添加 Loading 状态,这种情况添加封装统一的 Wrapper 类进行处理,如下:

sealed interface UiStateWrapper { object Loading : UiStateWrapper class Success<T>(val uiState: T) : UiStateWrapper class Failure(val exception: Throwable) : UiStateWrapper}

这种处理方式,并不需要在 UiState Entity 新增一个 isLoading 字段,保持 UiState 的 "纯洁性",同时也可以在 UI elements 中对 UiStateWrapper 做统一的处理,不必每个 UiState 中都出 Loading 的状态,当然,这是在 Loading 处理逻辑相同的前提下的。

整体而言,根据不同职责定义不同的 Entity 会让我们的代码逻辑相对合理,但是会增加一定的工作量以及会对要使用何种 Entity 产生混淆。所以还是需要根据自己的项目及团队情况决定是否需要精细化管理 Entity,大型团队建议采用这种方式。

如何组织代码?

代码建议按照业务模块方式进行组织,而非功能进行组织。大致如下:

# DO- Project - feature1 - ui - domain - data - feature2 - ui - domain - data - feature3

不要使用如下的方式:

# DO NOT- Project - ui - feature1 - feature2 - feature3 - domain - feature1 - feature2 - feature3 - data

采用 Feature 方式组织代码的优势大致有以下几点:

  1. 我们大概率都是在已有的项目中开发,而历史的项目中或多或少存在着一些历史技术债务,我们可以在开发特性的时候引入新的技术,这样不会对旧的目录结构产生过多影响;
  2. 后续可以很方便的对该特性进行改造,比如可以把这个文件夹移到一个单独的 module 中进行模块化相关的改造;
  3. 这方式在大型项目中的优势会更加明显;

速记手册

整理了一些关键知识点,可以保存图片定期回顾。

Android 官方现代 App 架构指南(android 应用架构)

官方材料

文章中的内容基本上都是参考官方文档以及 Youtube 上的 mad – arch 系列。都看到这里了建议您到官方文档中的 pathawy 地址中获取下现代 Android 应用架构徽章,只要阅读完下面的文档以及完成对应测试即可。

Android 官方现代 App 架构指南(android 应用架构)

  • Youtube

https://www.youtube.com/watch?v=TPWmfJq16rA&list=PLWz5rJ2EKKc8GZWCbUm3tBXKeqIi3rcVX&ab_channel=AndroidDevelopers

  • pathawy

https://developer.android.google.cn/courses/pathways/android-architecture

  • ui-layer

https://developer.android.google.cn/jetpack/guide/ui-layer

  • ui-layer/events

https://developer.android.google.cn/jetpack/guide/ui-layer/events

  • domain-layer

https://developer.android.google.cn/jetpack/guide/domain-layer

  • data-layer

https://developer.android.google.cn/jetpack/guide/data-layer

  • youtube playlist

https://www.youtube.com/playlist?list=PLWz5rJ2EKKc8GZWCbUm3tBXKeqIi3rcVX

  • Modern Android App Architecture quiz

https://developer.android.google.cn/courses/quizzes/android-architecture/architecture-layers?continue=https://developer.android.com/courses/pathways/android-architecture#quiz-/courses/quizzes/android-architecture/architecture-layers

最后

Android 官方现代 App 架构指南(android 应用架构)

今年的 Google I/O 发布了一个最新的官方示例 Now in Android,这个示例的完整度比之前的 JetNews、Sunflower 要高,后面也将基于这个仓库做进一步的说明解析,从一个完整项目的角度来看 Android 新推出的架构指南

  • Now in Android

https://github.com/android/nowinandroid

这里也分享一些珍藏资源,面试简历模板到大厂面经汇总,从大厂内部技术资料到互联网高薪必读书单,以及Android面试核心知识点(844页)和Android面试题合集2022年最新版(354页)等等,这些资料整理给大家,希望踩过的坑不要再踩,遭遇的技术瓶颈一次性消灭。

如果需要的话,可以顺手帮我点赞评论一下,直接私信我【笔记】免费领取!

部分内容展示如下

Android 官方现代 App 架构指南(android 应用架构)Android 官方现代 App 架构指南(android 应用架构)

01.Android必备底层技术

  • Java序列化:Serializable原理、Parcelable接口原理、Json、XML
  • 注解、泛型与反射:自定义注解、注解的使用、泛型擦除机制、泛型边界、Java方法与Arm指令、Method反射源码、invoke方法执行原理
  • 虚拟机:JVM垃圾回收器机制、JVM内存分配策略、Android虚拟机与JVM底层区别、虚拟机底层Odex本地指令缓存机制、虚拟机如何分别加载class与object、虚拟机类加载模型
  • 并发:Java线程本质讲解、线程原理、线程通信、UnSafe类、线程池
  • 编译时技术:OOP面向切面之AspectJ、字节码手术刀JavaSSit实战、字节码插桩技术(ASM)实战
  • 动态代理:动态代理实现原理、动态代理在虚拟机中运行时动态拼接Class字节码分析、ProxyGenerator生成字节码流程
  • 高级数据结构与算法:HashMap源码、ArrayList源码、排序算法
  • Java IO:Java IO体系、IO文件操作

Android 官方现代 App 架构指南(android 应用架构)

02.Framework

  • Binder:Linux内存基础、Binder四层源码分析、Binder机制、Binder进程通信原理
  • Handler:Loop消息泵机制、Message解析
  • Zygote:init进程与Zygote进程、Zygote启动流程、Socket通信模式、APP启动过程
  • AMS:ActivityThread源码分析、AMS与ActivityThread通信原理、Activity启动机制
  • PMS:PMS源码、APK安装过程分析、PMS对安装包的解析原理
  • WMS:PhoneWindow实例化流程、DecorView创建过程、ViewRootImpl渲染机制

Android 官方现代 App 架构指南(android 应用架构)

03.Android常用组件

  • Activty:Activity管理栈与Activity的启动模式、Activity生命周期源码分析
  • Fragment:Fragment生命周期深入详解、Fragment事务管理机制详解、性能优化相关方案
  • Service:Service启动模式分析、Service管理与通信方案、Service生命周期底层详解

Android 官方现代 App 架构指南(android 应用架构)

04.高级UI

  • UI绘制原理:setContentView()方法下到底做了什么、AppCompatActivity与Activity的区别、UI测量、布局、绘制的底层执行流程
  • 插件换肤:LayoutInflater加载布局分析、Android资源的加载机制、Resource与AssetManager
  • 事件分发机制原理:事件执行U形链与L形链、事件拦截原理
  • 属性动画:VSYNC刷新机制、ObjectAnimator与ValueAnimator源码讲解、Android属性动画:插值器与估值器
  • RecycleView:布局管理器LayoutManager详解、回收池设计思想、适配器模式原理
  • 高阶贝塞尔曲线

Android 官方现代 App 架构指南(android 应用架构)

05.Jetpack

  • Lifecycle:Lifecycle源码、Lifecycle高阶应用
  • ViewModel:ViewModel源码、ViewModel应用技巧
  • LiveData:LiveData源码
  • Navigation:Navigation源码
  • Room:Room源码、Room LiveData监听数据库数据变更刷新页面原理
  • WorkManager内核
  • Pagging原理
  • DataBinding:单向绑定、双向绑定、如何与RecyclerView的配合使用、底层原理

Android 官方现代 App 架构指南(android 应用架构)

06.性能优化

  • 启动优化:系统启动原理、Trace工具分析启动卡顿、类重排机制、资源文件重排机制
  • 内存优化
  • UI渲染优化:UI层级规范及对UI加载的影响、UI卡顿原因及修复、UI绘制、布局、测量原因以及处理方案
  • 卡顿优化:造成卡顿的原因分析、内存抖动与GC回收、回收算法
  • 耗电优化
  • 崩溃优化:项目崩溃异常捕获、优雅的异常处理方案、如何避免异常弹框
  • 安全优化:APP加固实现(防反编译,dex加固)、https防抓包机制(数据传输加载,客户端服务器端双向加密校验)
  • 网络优化:serializable原理、parcelable接口原理、http与https原理详解、protbuffer网络IO详解、gzip压缩方案
  • 大图加载优化:Glide巨图加载机制原理分析、大图多级缓存实现方案
  • 多线程并发优化
  • 储存优化:Android文件系统-sdcard与内存存储、Shared Preference原理、MMAP内存映射
  • 安装包优化:shrinkResources去除无用资源、合理设置多语言、webp实现图片瘦身、合理配置armable-v7的so库、Lint检查工具实践

Android 官方现代 App 架构指南(android 应用架构)

如果需要的话,可以顺手帮我点赞评论一下,直接私信我【笔记】免费领取!

07.音视频

  • C/C :数据类型、数组、内存布局、指针、函数、预处理器、结构体、共用体、容器、类型转换、异常、文件流操作、线程
  • H.265/H.265:音视频格式封装原理、编码原理、视频流H264的组装原理切片NAL单元、视频流H264码流分析、切片与宏快,运动矢量、信源编码器、高频滤波、帧间拆分与帧内预测、CTU,PU TU编码结构、DSP芯片解码流程、MediaPlayer与DSP芯片交互机制、投屏架构、MediaProjection与MeidiaCodec交互机制、H265码流交换
  • MediaCodec:dsp芯片、编解码器的生命周期、解码器中输入队列与解析队列设计思想、MediaCodec中平缓解码解析、MediaExtractor 多路复用、MediaMuxer合成器、MediaFormat格式
  • 音视频剪辑:视频剪辑、音频剪辑、音频合成、音谱显示、视频倒放
  • 音视频直播:硬编码、软编码、native实现rtmp推流、摄像头预览帧编码NV21转YUV、视频画面封装拼接Packet包、音频流数据拼接Packet包、RtmpDump实时同步发送音视频数据、MediaProjection、Medicodec编码H264码流、rtmp推流
  • OpenGL与音视频解码:OpenGL绘制流程、矩阵、Opencv详解、人脸识别效果实现
  • OpenGL特效:CPU与GPU运行机制详解、世界坐标,布局坐标,与FBO坐标系、图像镜像与旋转处理、人脸定位与关键点定位、大眼效果、贴纸效果、美颜效果
  • FFmpeg万能播放器:FFmpeg结构体、声音播放原理、Surface的渲染、像素绘制原理与对齐机制、音视频同步原理、视频播放器整体架构
  • Webrtc音视频通话:WebRtc服务端环境搭建与Webrtc编译、1v1视频通话实现方案、群聊视频通话实现思路、多对多视频会议实现、1V1音视频通话实现

Android 官方现代 App 架构指南(android 应用架构)

08.开源框架原理

  • Okhttp
  • Retrofit
  • RxJava
  • Glide
  • Hilt
  • Dagger2
  • EventBus
  • 组件化、插件化、热修复等

Android 官方现代 App 架构指南(android 应用架构)

09.Gradle

  • Groovy语法
  • Gradle Android插件配置
  • Gradle实践等

Android 官方现代 App 架构指南(android 应用架构)

10.kotlin

  • Kotlin语法
  • 扩展使用
  • 进阶使用
  • 实践等

Android 官方现代 App 架构指南(android 应用架构)

11.Flutter

  • Dart语法
  • UI
  • 进阶使用
  • 优化
  • 实践等

Android 官方现代 App 架构指南(android 应用架构)

12.鸿蒙

  • Ability组件
  • 分布式任务
  • 事件总线
  • 鸿蒙线程
  • UI自定义控件等

Android 官方现代 App 架构指南(android 应用架构)

如果需要的话,可以顺手帮我点赞评论一下,直接私信我【笔记】免费领取!

Android路漫漫,共勉!

Android 官方现代 App 架构指南(android 应用架构)Android 官方现代 App 架构指南(android 应用架构)

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

(0)
上一篇 2023年5月13日 上午10:42
下一篇 2023年5月13日 上午10:58

相关推荐

  • wap低代码开发平台开源

    随着移动互联网的快速发展,越来越多的企业开始意识到移动应用的重要性。然而,开发一款高质量的移动应用并不是一件容易的事情。传统的开发方式需要耗费大量的时间和资源,而且往往需要专业的开…

    科研百科 2024年2月28日
    59
  • 在家隔离的人可以考虑的美国十所顶级在线大学(美国学校隔离)

    1.阿肯色大学小石城分校 地点:小石城,AR 学费:$13751 毕业率:43% 认可:美国高等教育委员会 学校简介 学校类型:公共 在线学位:商业、通信、刑事司法、教育、健康和社…

    科研百科 2024年4月6日
    68
  • 统计学科研项目名称大全

    统计学科研项目名称大全 统计学是一门研究数据收集、处理、分析和解释的学科,而科研项目则是统计学应用于实践的重要形式。随着科技的发展,越来越多的科研项目开始使用统计学方法来进行数据分…

    科研百科 2024年8月12日
    24
  • 一文通晓游戏项目管理:从甘特图到版本管理(项目管理甘特图软件)

    作者:Hao ️游戏策划→研发PM 8年从业经验,20 项目经历 游戏设计丨项目管理丨敏捷教练 知乎专栏丨小红书丨小宇宙 一、甘特图与里程碑规划 在游戏项目管理的过程中,随着团队人…

    科研百科 2024年6月11日
    46
  • 河南省双高项目管理

    河南省双高项目管理 河南省作为我国的一个重要省份,一直以来备受关注。近年来,河南省政府高度重视双高项目管理,通过不断完善相关政策和措施,促进了相关领域的发展。本文将介绍河南省双高项…

    科研百科 2024年10月20日
    0
  • 项目管理甘特图软件

    项目管理甘特图软件 项目管理是企业发展的重要组成部分,而甘特图软件则是项目管理中不可或缺的工具。本文将介绍项目管理甘特图软件的基本概念、用途和优点,帮助企业管理者更好地了解和使用项…

    科研百科 2024年9月28日
    18
  • 工会经费全套账务处理(工会经费全套账务处理流程)

    根据会计准则以及会计制度的规定,企业发生工会经费、职工教育经费、福利费的支出都是需要通过“应付职工薪酬”核算的。工会经费按照不超过工资薪金总额2%计提。   1、计提工会经费时,按…

    科研百科 2023年10月5日
    119
  • 实验室cnas体系

    实验室cnas体系 实验室cnas体系是一种标准化的实验室管理流程,旨在确保实验室的质量和安全。cnas体系由国际实验室协会(ILSI)制定,涵盖了实验室的整个生命周期,从实验室规…

    科研百科 2024年11月13日
    1
  • jira怎么使用

    jira是一款功能强大的开源项目管理软件,可以帮助开发者更好地管理项目进度、代码审查、问题跟踪等。本文将介绍如何使用jira来管理我们的项目。 首先,我们需要安装jira。可以通过…

    科研百科 3天前
    0
  • 盘活存量资产 保障项目用地(盘活存量建设用地)

    中国徐州网-徐州日报讯(徐报融媒记者 陈强 骆耀明 通讯员 何峰 左连平)“农村集体经营性建设用地入市给我们解决了大问题!非常感谢自然资源部门给我们办理了用地手续,项目终于可以落地…

    科研百科 2022年9月11日
    176