DDC 项目地址:DDComponentForAndroid

博客:Android彻底组件化方案实践

1. 组件化的意义

随着项目的发展,代码越来越臃肿,多人开发管理趋于复杂化。再加之版本定制化增多,业务模块管理不合理。借助模块化将项目分而治之,降低耦合,在定制业务方面,可以按需打包,减少无关业务的代码占用。

DDComponentForAndroid 组件化作者着重解决:代码解耦、组件单独调试、数据传递、UI跳转、生命周期、集成调试、代码隔离。(详见作者博客)

2. 实践

2.1 新建项目

新建 ComponentDemo 项目,添加库:baselib、baseres、componentlib、componentservice。如图所以:

  • baselib 基础代码,公共代码,工具类
  • baseres 公共资源、theme、baseapplication
  • componentlib 路由框架
  • componentservice 组件服务

依赖关系:

  • app -> componentservice -> baseres -> baselib

  • componentservice -> componentlib

2.2 build-gradle 插件

这个插件是组件化的核心,会自动判断apply com.android.library还是com.android.application。可以将此插件发布的 maven 库中再引用。

首先利用 ./gradlew uploadArchives 命令生成对应的 jar 文件提供给 build.gradle 使用

2.3 修改配置
  • 在根目录的 gradle.properties 中添加:
1
mainmodulename=app //插件标识为主项目
  • 在 app 的 gradle.properties 中添加:
1
2
3
isRunAlone=true //标识是否需要单独调试
debugComponent=onecmodule,secondemodule//调试下用于引用组件库
compileComponent=com.atu.onemodule:onemodule,secondmodule //集成测试用于引用组件aar文件(包名+组件名)和库 或maven 库
  • 在 app 的 build.gradle 中修改:apply plugin: ‘com.android.application’ 为 apply plugin: ‘com.dd.comgradle’ 让插件管理 application 或 library。接着添加:
1
2
3
4
combuild {
applicationName = 'com.atu.componentdemo.app.MainApplication'
isRegisterCompoAuto = true //告知插件加载方式
}
2.4 业务模块

新增两个模块 onemodule 和 secondemodule

  • 在 module 的 - 中添加:
1
isRunAlone=true //标识是否需要单独调试
  • 在 module 的 build.gradle 中修改:apply plugin: ‘com.android.library’ 为 apply plugin: ‘com.dd.comgradle’ 让插件管理 application 或 library。
  • 在 main 目录下配置 runalone 文件

  • 在 module 的 build.gradle 中添加:
1
2
3
4
5
6
7
resourcePrefix "one_" //避免资源重名
...
combuild {
applicationName = 'com.atu.one.runalone.application.OneApplication'
isRegisterCompoAuto = true //告知插件加载方式
}
2.6 路由
  • 组件交互

在 oneapplike 添加和移除 服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class OneAppLike implements IApplicationLike{
Router router = Router.getInstance();
@Override
public void onCreate() {
router.addService(OneModuleService.class.getSimpleName(),new OneServiceImpl());
}
@Override
public void onStop() {
router.removeService(OneModuleService.class.getSimpleName());
}
}

在 componentService 中定义服务

1
2
3
4
public interface OneModuleService {
Fragment getOneModuleFragment();
}

在 OenModule 提供具体实现类

1
2
3
4
5
6
public class OneServiceImpl implements OneModuleService {
@Override
public Fragment getOneModuleFragment() {
return new OneFragment();
}
}

Router 中注册

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class OneAppLike implements IApplicationLike{
Router router = Router.getInstance();
@Override
public void onCreate() {
router.addService(OneModuleService.class.getSimpleName(),new OneServiceImpl());
}
@Override
public void onStop() {
router.removeService(OneModuleService.class.getSimpleName());
}
}

获取服务

1
2
3
4
5
6
7
Router router = Router.getInstance();
if (router.getService(OneModuleService.class.getSimpleName()) != null) {
OneModuleService service = (OneModuleService) router.getService(OneModuleService.class.getSimpleName());
fragment = service.getOneModuleFragment();
ft = getSupportFragmentManager().beginTransaction();
ft.add(R.id.fl_main_content, fragment).commitAllowingStateLoss();
}
  • UI 跳转

在 secondmodule 中用实现 IComponentRouter 的SecondUIRouter 声明处理的短链。

在 secondapplike 中注册和注销 UIRouter

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class SecondAppLike implements IApplicationLike{
UIRouter uiRouter = UIRouter.getInstance();
SecondUIRouter secondUIRouter = SecondUIRouter.getInstance();
@Override
public void onCreate() {
uiRouter.registerUI(secondUIRouter);
}
@Override
public void onStop() {
uiRouter.unregisterUI(secondUIRouter);
}
}
2.7 上传 aar 到 maven 库

在组件的 gradle 的 assembleRelease 下自动利用插件生成对应的 arr 文件,位于 componentrelease 文件下。

在根目录下添加,nexus_maven.gradle 文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
apply plugin: 'maven'
apply plugin: 'signing'
configurations {
deployerJars
}
repositories {
mavenCentral()
}
// 判断版本是Release or Snapshots
def isReleaseBuild() {
return !VERSION.contains("SNAPSHOT");
}
// 获取仓库url
def getRepositoryUrl() {
return isReleaseBuild() ? RELEASE_URL : SNAPSHOT_URL;
}
uploadArchives {
repositories {
mavenDeployer {
beforeDeployment {
MavenDeployment deployment -> signing.signPom(deployment)
}
pom.version = VERSION
pom.artifactId = ARTIFACT_ID
pom.groupId = GROUP_ID
pom.packaging = PACKAGING
repository(url: getRepositoryUrl()) {
authentication(userName: NAME, password: PASSWORD) // maven授权信息
}
}
}
}
// 进行数字签名
signing {
// 当 发布版本 & 存在"uploadArchives"任务时,才执行
required { isReleaseBuild() && gradle.taskGraph.hasTask("uploadArchives") }
sign configurations.archives
}

在 Module 的 gradle.properties 添加上传 maven 库的版本信息等:

1
2
3
4
5
6
7
8
9
10
VERSION=1.0.0
GROUP_ID=com.atu
ARTIFACT_ID=onemodule
PACKAGING = aar
RELEASE_URL=http://127.0.0.1:8081/repository/Atu/
SNAPSHOT_URL=http://127.0.0.1:8081/repository/Atu/
NAME=admin
PASSWORD=admin123

利用命令 ./gradlew uploadArchives 上传到 maven库。

项目地址:ComponentDemo