Android 架构 - 组件化

2024-01-03 18:59:19

一、概念

组件化是基于可重用目的,对单个功能进行开发,提升复用性降低耦合度。多个功能组件起来就是一个业务组件,多个业务组件组合起来就是一个应用,因此去除了模块间的耦合,使得按业务划分的模块成了可单独运行的业务组件。(组件化只是一定程度上的独立,还是依附于整个项目中,想完全独立详见插件化)

  • 功能复用:每个组件都是一个单独的功能,可被不同的模块甚至不同的应用所使用。
  • 提高效率:每个组件都是一个可单独编译运行的APP,由于拆分使得代码量少,调试起来快。
  • 协同开发:组件之间相互独立,使得不同的开发人员能专注于各自的功能开发互不影响。

1.1?需要考虑的问题

组件分层、切换模式按需编译、组件通信(路由框架)、组件生命周期(组件在应用中存在的时间,组件是否可以按照需求动态使用,涉及到组件的加载卸载等管理问题。)

1.2?插件模式

在组件的构建脚本 build.gradle?中指定,指定为集成模式(Library)可以被其它组件调用,指定为组件模式(Application)可以独立运行调试。

com.android.application项目构建后输出?apk 包,在调试时是一个应用能单独编译运行。
com.android.library项目构建后输出 aar 包,在打包时是一个库文件集成到项目中。
com.android.test配置一个 Android Test 工程。
//写法一(和别的一起写)
plugins {
    id 'com.android.library'
    id 'org.jetbrains.kotlin.android'
}
//写法二(分开写)
apply plugin: 'com.android.library'

1.3?创建组件

File→New→New Module。业务组件需要调试选择【Phone &?Tablet】,功能组件(最后还是通过业务组件来调试)基础组件只用来集成选【Android?Library】。?

二、结构划分

依赖关系是上层依赖下层,修改频率是上层高于下层。对于业务组件由于存在页面跳转、方法调用、事件通信等问题需要使用路由通信,其它层组件不存在耦合问题封装成?Library 即可。

app壳主工程,应用的入口,将业务组件打包成一个APP(打包环境、签名、混淆、主题等配置工作)。
业务组件业务组件之间无直接关系,通过路由进行通信。既可以作为 Application 单独编译运行调试,又可作为 Library 集成到项目中。(主页、消息、商城)
功能组件功能组件是为了支撑业务组件的某些功能而独立划分出来的组件(对公用的功能进行封装),功能实质上跟项目中引入的第三方库是一样的。(业务组件可以直接依赖基础组件去实现功能)
基础组件实现路由、一般是第三方框架、第三方SDK,修改频率极低。(Retrofit、Glide)

三、统一配置

3.1?创建并引入 config.gradle

创建方式是对 Project?的?build.gradle?使用 Ctrl+C?和?Ctrl+V,命名为 “config.gradle” 清空里面的代码并同步一下,然后在?Project?的?build.gradle?中引用刚才创建的文件。

3.2?切换组件模式的全局变量?isDebug

?

四、基础组件

4.1?创建?lib_common

4.2?提供?BaseApplication

提供?BaseApplication?供app壳和其它组件继承。

4.3?统一权限声明?AndroidManifest

声明了项目中用到的所有权限 user-permission 和 uses-feature,这样其它组件就无需在自己的 AndroidManifest.xm 声明自己要用到的权限了。

?

4.4?统一第三方依赖?build.gradle

????????统一所有组件中用到的第三方库和jar包,具体写在?config.gradle?中再引入。使用 imlemntation?添加的依赖只对当前组件有效,使用 api?添加的依赖对其上层组件同样有效,这样依赖于基础组件的组件就不用再添加相同的依赖了。

????????项目中某个组件会被其它组件重复依赖,在集成构建应用时?Gradle 会剔除重复的 arr?包,这样就不会存在好几份重复的代码了。而第三方库和我们的项目可能都依赖了相同的库(例如?Glide?中也依赖了?OkHttp)就会导致重复加载,解决办法是找出相同的库根据组件名或包名排除。

4.5?公共类

封装了项目中的 Base类、Utis工具类等,公用的 Widget控件、业务组件中都用到的数据也应放在这里(例如 SharedPreferences 和 DataBase 中的登录数据)。

4.6?资源文件

将公共的?drawable、shape、layout、strings、colors、dimens、styles、theme 等资源文件放在这里,提升复用性,保证主题统一、避免文件名冲突。必须放在组件中的话,一定要规范命名前缀。

五、核心组件(业务组件同理)

5.1?创建 module_core

5.2?创建 debug?包

在业务组件中创建?debug?包,用于存放只在组件模式下使用的文件(如程序入口?Launcher?Activity、自定义Application),在集成模式下会被剔除不参与打包(见下方build.gradle中配置)。

在业务组件的?src/main/java?目录上右键→New→Package。(不推荐在组件的其它层级上创建目录存放,切换到Android视图不会显示)

5.3 两份 AndroidManifest

????????在组件模式下,也会因为<application>标签配置、自定义Application 、指定启动入口(Launcher?Activity)而在?AndroidManifest?中进行注册,但在集成模式下打包到一起时存在重复和冲突(桌面上好几个启动图标、只能注册一个自定义的Application、同一个权限无须多次申请)。

? ? ? ? 由于可以在?build.gradle?中动态指定组件的模式,因此可以分别为两种模式加载不同的?AndroidManifest。组件模式下的 AndroidManifest?写在?debug?目录中,在集成模式下剔除。

  1. 将?AndroidStudio?为组件自动创建的?AndroidManifest?复制一份到?debug?目录,对 <manifest>?标签添加?package 属性指定为业务组件的包名。?
  2. 修改自动创建的?AndroidManifest,将 <application>?的属性(保留了theme是方便组件中用到该主题的Activity不用每个都要单独设置)以及程序入口?Launcher?Activity 删除,只保留四大组件的注册,对 <manifest>?标签添加?package 属性指定为组件的包名。

5.4 修改 build.gradle

  1. 在组件模式下才是一个应用,因此需要动态配置 applicationId。
  2. 在 <android> 标签下使用 <sourceSets> 动态指定不同模式下加载的 AndroidManifest?文件,并剔除?debug?包下的文件不参与集成模式下的打包。
  3. 将版本替换成?config.gradle?中定义的。
  4. 在 <dependencies>?中引入依赖。

5.5?程序入口?LauncherActivity

用于初始化数据后启动目标?Activity(不需要可以省略),因此写在?debug?目录下,不用?setContentView(),传入目标?Activity?需要的?Intent?参数即可。

六、搬空app壳

6.1?搬运 MainActivity

将 app 中的 MainActivity.class?和?activity_main.xml?剪切至?module_core?中,并将?AndroidManifest?中的?MainActivity?注册(包含程序入口)也剪切至 module_core?中只保留 <application>?标签。

6.2?修改 AndroidManifest

每个组件都会有自己的清单,最终会打包合并成一个文件,需要解决属性冲突。分别对?app?的 <manifest>?和 <application>?添加如下代码。

manifest?标签xmlns:tools="http://schemas.android.com/tools"
application?标签tools:replace="android:label,android:icon,android:theme,android:allowBackup"

6.3?修改 build.gradle

将 <defaultConfig>?和 <dependencies>?下的配置统一定义到?config.gradle?中并引入,并根据组件模式动态的引入组件。

文章来源:https://blog.csdn.net/HugMua/article/details/135365022
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。