5

2022 Android 官方现代应用架构解读 – 概述

 2 years ago
source link: http://www.androidchina.net/12494.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

2022 Android 官方架构指南系列文章

面对的挑战

随着 App 功能的不断增加,其代码实现复杂度将会呈指数级增加,具体体现在以下几个方面:

  1. 允许 App 的功能要能顾灵活的扩展与收缩;
  2. 保证 App 的稳定性与健壮性;
  3. 使 App 容易测试;

所以在 App 开发的过程中必须要有一个合适的架构指南来帮助完成上述挑战。

为了满足上面的一些需求,整体架构至少需要采用以下几个大的设计原则:

 分离关注点

分离关注点是解决复杂问题的一种常见的解决方案,它是将一个计算机程序拆分为不同部分的设计原则。每一部分都有自己需要关注的焦点。从而达到将一个复杂问题拆解成多个简单问题的效果。

如 ActivityFragment 主要职责是绘制数据与响应用户的操作事件;于此同时,Android 系统可以根据当前系统的资源状况随时对其进行销毁。如果想要在此部分中编写业务逻辑以及耗时操作的话,将会增加其复杂度,从而导致页面开发变得难于维护(容易产生bug)。

关注分离点这种解决问题的思路并非仅适用于计算机编程问题,比如阿德勒心理学中的客体分离概念也与此大同小异。

数据驱动页面

数据是项目的核心,也是状态的最终保存者。而视图,只不过是一种能够由数据延迟计算出来的最终结果而已,它本身不存储状态。

这也是近些年响应式编程的流向的原因之一,将更多的精力放在的复杂数据的处理上,View 只需要观察数据变化并做出响应即可。

除了上面的指导原则之外,还有一个官方文档中没有提到的一些设计准则仍然非常有用:

  • KISS:同一问题的不同解决方案中,应选择简单的那个方案;
  • SOLID:面向对象编程的一些基本原则;
  • 更多对开发人员有用的定律、理论、原则和模式;

根据以上的架构指南,一个 App 至少应该拆分为两层,UI 层及数据层:

  • UI Layer – 在屏幕上显示应用数据。
  • Data Layer – 包含应用的业务逻辑并公开应用数据。

还可以额外添加一个 Domain 层,以重用界面层的业务逻辑或是拆分业务避免大型类。整体如下:

Untitled.png

App Arch Layer Design

UI Layer

UI Layer 主要包含了以下几个部分:

  • View Container:View 的容器,是 View 渲染的入口,一般是指 Activity、Fragment;
  • UI elements:UI 元素,是用来渲染界面的,可以是 Views 也可以是 Compose 函数;
  • States holders:UiState 的持有者,是最终组装UiState的地方,一般是 ViewModel 类;
  • event:用户的交互事件,通常需要在产生、更新数据,代理给 ViewModel 处理;
  • UiState:UI 的状态数据,用来渲染 UI elements 的数据,通过观察者方式提高;

image.png

UI Layer 主要是做了一下几件事情:

  • 将 App 中的数据转换成容易被 UI Elements 渲染的数据(UiState)。这部分转换主要发生在 State Holder 中。
  • 将 UiState 转换为对应的 UI elements 展示给用户。这部分主要发生在 Activity 或 Fragment 中,不论 Activity 和 Fragment 使用的是 View 还是 Jetpack Compose 构建的。
  • 接收 UI elements 中的输入事件,并且根据需要做出响应。

Domain Layer

Domain Layer 主要是可以做以下及件事情:

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

Domain Layer 是一个可选层,可以根据自己项目的复杂情况决定是否使用。Domain Layer 主要是有不同的 UseCase(有的框架中也称作 Interactor)组成,其依赖关系大致如下:

image.png

Data Layer

Data Layer 主要做了下面两件事情:

  • 通过 DataSource 封装系统及三方 API;
  • 通过 Repository 使用 DataSource 封装业务逻辑,并暴露给使用者;

一个业务模块中可以包含一个或者多个 Repository ,每个 Repository 中包含零个或多个 DataSourceDataSource 根据其来源可以分为 LocalDataSourceRemoteDataSource 等。大致依赖关系如下:

image.png

以上几层内容中会存在大量类的初始化及注入管理问题,如果处理不好将会导致一些不必要的麻烦。这种问题有两种解决方案:

  1. 依赖注入:依赖注入使类能够定义其依赖项而不构造它们。在运行时,另一个类负责提供这些依赖项。一般是使用注解方式,适合大中型项目,如 Hilt
  2. 服务查找:服务查找的方式一般是维护一个注册表,所需的依赖都可以在这个注册表中查找;一般是使用相对简单,适合中小型项目,如 koin

官方推荐使用 Hilt 来进行依赖管理,如果你的项目中在使用其他的依赖管理方式,并且没有遇到问题的话,那么继续使用当前的框架即可。

当然还是会有一些其他的最佳实践需要我们去遵守:

  1. 不要将数据在 Android 四大组件中处理,他们有自己的生命周期我们很难控制;
  2. 尽量减少对 Android 类(ContextActivity等)的依赖,减少耦合,提高可测试性;
  3. 需要明确各个模块中的职责,在各自的分层中仅做自己职责范围内的事情,减少耦合;
  4. 每个模块仅仅只需暴露自己应该提供的功能,保持越简单越好;
  5. 应尽量设计离线模式,用户在网络不可用的情况下,仍然可以使用 App;

更多详细内容可查看 官方文档 。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK