组件化实践

本文介绍了Android组件化的重要性和实施步骤,包括组件化架构设计、模块单独运行、初始化问题、跨模块方法调用的解决方案。通过组件化,可以将大型项目拆分成独立的业务和功能组件,便于管理和维护。文章详细讲解了如何处理模块初始化、启动Activity、跨模块通信等问题,并提到了使用Arouter框架进行组件间的交互。同时,文章还提醒了在组件化过程中需要注意的资源冲突和代码隔离策略。
摘要由CSDN通过智能技术生成

近期公司有组件化的打算,因此对市面上的方案进行了调研,目前已经整理出一套作为项目组件化的方案,这里分享一波,当然组件化是没法一步到位的,中间肯定少不了踩坑优化,所以本篇也会持续更新。

那么我们先说说组件化是干嘛的吧,组件化就是将单模块的项目拆成多个,并且每个模块可以单独运行。

WTF!!!这么简单?

对概念就是这么简单,但当我们去做的时候就会发现几个问题

  1. 模块如何单独运行
  2. 拆成独立模块后初始化问题(组合运行和独立运行的时候怎么初始化)
  3. 跨模块方法调用(如何启动Activity、跨模块获取数据)
  4. 模块独立运行时跨模块方法调用

那么要想组件化就需要解决上面这几个问题,所以接下来就是围绕这几个问题展开讨论,不过在这之前我们先看看整体架构有个大概的认识。

组件化架构图

从组件的划分上分为四层,从上往下依次为

  • App壳工程:负责管理各个业务组件和打包APK,没有具体的业务功能。
  • 业务组件层:根据不同的业务构成独立的业务组件。
  • 功能组件层:对上层提供基础功能服务不包含业务,如地图、拍照、日志等。
  • 组件基础设施:Base类、第三方Sdk、View等一些通用代码。

这里单独说下业务组件和功能组件,一个典型的业务组件工程结构是这个样子:

以上图为例,它包含三个模块(两个Library和一个Application):

  • jd :组件代码,它包含了这个组件所有业务代码并实现了jd-api的接口。
  • jd_api:组件的接口模块,专门用于与其他组件通信,只包含 Model、Interface 和 Event,不存在任何业务和逻辑代码。
  • jd_app 模块:用于独立运行 app,它直接依赖组件模块,只要添加一些简单的配置,即可实现组件独立运行。

你可能会问为什么要有个jd_api模块,其实和接口隔离是一个意思,jd_api模块存放着jd模块需要对外暴露的接口,jd模块去实现这些接口,当别的模块想要调用jd模块方法的时候拿到的是jd_api模块的接口对象,从而隔离jd模块,只不过这些接口是装在一个独立的library中,之所以这样也是因为业务模块粒度太大,包含的代码量较多,如果将接口放在业务模块内,既不利于隔离不同实现,还会因为获取接口实现类增加很多冗余的判断代码,所以将接口单独作为一个library模块,具体实现类的话根据具体业务场景依赖对应的业务模块。

以jd模块为例,他需要依赖jd_api并实现它的接口

dependencies {
    ...
    implementation project(':component-jd:jd_api')
  	...
}

而独立运行的jd_app模块则需要依赖接口模块jd_api和业务具体实现模块jd

dependencies {
    ...
    runtimeOnly project(':component-jd:jd')//runtimeOnly可以防止我们在写代码的时候直接引用到jd模块的类
    implementation project(':component-jd:jd_api')
  	...
}

如果哪天对于jd的业务有新的实现,我们只需要修改runtimeOnly project(':component-jd:jd')依赖即可,至于怎么拿到接口实现类是通过Arouter这个框架去获取的,后面会说。

对于功能模块来说,同样也需要用接口隔离,但与业务模块不同的是功能模块本身相对独立没有业务逻辑,所以不需要单独为接口创建一个library,直接把对外暴露的接口定义在功能模块内即可,外部只需通过工厂拿到具体实现类进行操作。

以支付功能模块为例:

在支付模块内有一个接口IPay进行隔离,RandomPay为接口具体实现类,业务模块要想调用支付模块的方法只需通过PayFactory拿到IPay实现类操作即可。

模块如何单独运行

模块要想单独运行只需要新建一个Application壳工程用来作为独立运行的入口,模块本身永远是library,然后壳工程依赖模块即可,那么一个模块的目录将变成如下这样:

projectRoot
+--app
+--component_module1(文件夹)
	|  +--module1(业务模块library)
	|  +--module1_api(业务组件的接口模块,专门用于与其他组件通信library)
	|  +--module1_app (独立运行的壳工程Application)

app模块是全量编译的application模块入口,module1是业务library模块,module1_api是业务组件的接口library模块,module1_app是用来独立启动 module1的application模块。

对于独立运行的module1_app模块只需依赖业务接口模块和业务模块

dependencies {
  	...
  	runtimeOnly project(':module1')
    implementation project(':module1_api')
  	...
}

对于全量编译的app模块则根据所需业务依赖对应的业务接口模块和业务模块

dependencies {
  	...
  	runtimeOnly project(':module1')
    implementation project(':module1_api')
    runtimeOnly project(':module2')
    implementation project(':module2_api')
  	...
}

由于有专门用于单独启动的module1_app模块的存在,业务的 library模块只需要按自己是library模块这一种情况开发即可,而为了让业务模块单独启动所需要的配置、初始化工作都可以放到module1_app模块里,并且不用担心这些代码被打包到最终Release的App中。

拆成独立模块后初始化问题

初始化的逻辑我们可以细分为两类

  1. 通用的初始化逻辑
  2. 每个模块个性化的初始化逻辑

对于通用的初始化逻辑可以写在Base模块的Application中

public class BaseApplication extends Application {
   

    private static Application sApplication;

    @Override
    public void onCreate() {
   
        super.onCreate();
        sApplication = this;
        initARouter(this);
    }

    public void initARouter(Application application) {
   
        if (BuildConfig
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值