前言
在之前的文章中,我们讲解了云音乐应用的基本库构建。今天,我们将进行一场 组件化代码重构
基于组件的库包系列文章 如下:
Android组件开发(四)——Process Keep-Alive组件的封装
Android组件开发(七)——教你分析项目需求,从零开始实现
项目地址 : github.com/ByteYuhb/an…
项目演示 :
1. 组件化重构效果
下面是我们重建前后的框架图对比:
重构前:
重构后
ft_xxx
代表业务层模块lib_xxx
表示一个基础库模块
重构后的架构图如下 :
重构前的代码业务被封装在宿主应用程序中,业务耦合严重。如果修改了一个业务模块,就需要对整个app进行完整的测试,测试工作量巨大。
和 重构之后,我们只需要独立调试一个应用。
重构框架结构: 所有业务组件都通过 **ft_base_service**
交流
2. 组件化重构指南
-
- 单个业务可以单独调试,也可以作为lib提供给宿主应用
-
- 不允许直接调用同级的模块。比如我们的ft_home组件是不允许直接调用ft_login组件的,否则就不存在组件化的意义了。
-
- 组件之间的通信不能通过显示的类文件直接跳转。可以考虑使用 ARouter 框架进行解耦。
-
- 每个组件都可以打包成aar或者jar,上传到maven私服。宿主机使用时,可以直接引用私服中的aar包。
如果你能做到以上几点,你的应用就可以称为组件化框架应用。
3.组件化重构思路
-
- 拆除 : 拆迁代码、拆迁资源、拆迁施工
由于所有业务和资源都耦合在宿主应用程序中,因此需要将代码和资源分离到相应的模块中
当然我们的build.gradle也需要拆分成不同的模块
- 拆除 : 拆迁代码、拆迁资源、拆迁施工
-
- 抓住 : 提供外部接口
组件之间没有直接的通信,需要通过暴露的接口进行外部通信。
- 抓住 : 提供外部接口
-
- 测量 : 重复测试
重构后代码需要反复测试,防止出现意外bug
- 测量 : 重复测试
4. 组件化重构过程
我在这里登录业务 ft_login
例如:
1. 步骤1 : 首先新建一个业务模块 ft_login
,然后在宿主应用程序中提取与登录功能相关的代码和资源 ft_login
中间
2. 第2步 :将与登录构建相关的依赖项分配给 ft_login
正在建设中。
3. 第 3 步 : 单独调试功能的实现
-
3.1:在
gradle.properties
在以下位置创建一个全局变量:isRunAlone=真
-
3.2:在
构建.gradle
中间:if(isRunAlone.toBoolean()){
应用插件:'com.android.application'
} 别的{
应用插件:'com.android.library'
}安卓 {
compileSdkVersion 33
构建工具版本“33.0.0”默认配置 {
if(isRunAlone.toBoolean()){
applicationId 'com.anna.ft_login'
}
...
}
源集{
主要的 {
爪哇{
srcDirs = ['src/main/java']
}
资源 {
srcDirs = ['src/main/res']
}
添加{
srcDirs = ['src/main/aidl']
}
显现 {
if(isRunAlone.toBoolean()){
srcFile 'src/main/manifest/AndroidManifest.xml'
} 别的 {
srcFile 'src/main/AndroidManifest.xml'
}
}
}
}
}
def 依赖列表 = [rootProject.depsLibs.okhttp,
rootProject.depsLibs.gson,
rootProject.depsLibs.appcompact,
rootProject.depsLibs.design,
rootProject.depsLibs.eventbus,
rootProject.depsLibs.arouterapi,
':lib_network', ':lib_common_ui', ':ft_base_service']依赖{
if(!isRunAlone.toBoolean()){
依赖列表.each { 字符串依赖 ->
依赖.startsWithAny(':lib', ':ft')? compileOnly(project(depend)):compileOnly(depend){
开关(依赖){
案例 rootProject.depsLibs.arouterapi:
排除组:'com.android.support'
休息;
}
}
}
} 别的 {
依赖列表.each { 字符串依赖 ->
依赖.startsWithAny(':lib', ':ft')?实施(项目(依赖)):实施(依赖){
开关(依赖){
案例 rootProject.depsLibs.arouterapi:
排除组:'com.android.support'
休息;
}
}
}
}
//路由注解处理器
annotationProcessor rootProject.depsLibs.aroutercompilertestImplementation 'junit:junit:4.+'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'}
复制代码
个别调试状态注意四点 :
- 1.参考应用插件
- 2.引入applicationId
- 3. 为sourceSets引入不同的构建路径
- 4.导入的库需要单独调试状态下使用
执行
导入,不能使用只编译
实现以上四点, 只需打开 isRunAlone 即可作为单独的应用程序运行 .
4. 第四步:组件之间的通信
在这里,我们介绍一个 ft_base_service
模块,该模块用于实现组件之间的通信,需要调用其他业务模块才能使用该模块进行通信,
业务模块和 ft_base_service
通讯使用 路由 ARouter
:
关于 路由器
使用可以参考这篇文章:
Android开源系列——组件化框架Arouter——(一)使用详解
- 1. 创建
ft_base_service
,在这个模块中:创建一个登录服务
接口继承提供者
引入 ARouter 依赖
:
安卓 {
javaCompileOptions {
注释处理器选项 {
参数 = [AROUTER_MODULE_NAME:project.getName(),AROUTER_GENERATE_DOC:“启用”]
}
}
}
//路由核心api
实现 rootProject.depsLibs.arouterapi
//路由注解处理器
annotationProcessor rootProject.depsLibs.aroutercompiler
复制代码
创建登录服务:
公共接口 LoginService 扩展 IProvider {
boolean hasLogin();
无效登录(上下文上下文);
}
复制代码
- 2. 在
ft_login
在业务模块中实现LoginService接口
注意,因为这里使用了 ARouter 注解,所以也需要引入 路由器
依靠
@Route(path = "/login/login_service")
公共类 LoginServiceImpl 实现 LoginService {
上下文上下文;
@覆盖
公共布尔 hasLogin () {
返回 UserManager.getInstance().hasLogined();
}
@覆盖
公共无效登录(上下文上下文){
LoginActivity.start(context);
}
@覆盖
公共无效初始化(上下文上下文){
Log.d("TAG", "LoginServiceImpl is init");
}
}
复制代码
-
3. 在
ft_base_service
模块对登录服务
依赖注入接口公共类 LoginImpl {
@Autowired(name = "/login/login_service")
公共登录服务 mLoginService;
私有静态 LoginImpl mLoginImpl = null;
公共静态 LoginImpl getInstance () {
if (mLoginImpl == null) {
同步(LoginImpl.class){
if (mLoginImpl == null) {
mLoginImpl = new LoginImpl();
}
返回 mLoginImpl;
}
}
返回 mLoginImpl;
}私人登录Impl(){
ARouter.getInstance().inject(this);
}
公共布尔 hasLogin (){
返回 mLoginService.hasLogin();
}
公共无效登录(上下文上下文){
mLoginService.login(上下文);
}}
复制代码
作者使用了一个 单例类 LoginImpl , 在构造函数中 登录服务
依赖注入
ARouter.getInstance().inject(this);
那么宿主app或者其他模块在引用登录业务功能时,需要依赖 **ft_base_service**
模块,并使用 **LoginImpl**
接口可以使用。
这里解释一下,我们通常使用 四分量跳跃 也可以用这个方法来处理,只需要在服务接口中定义跳转接口即可。当然也可以使用Arouter的Activity跳转方式或者Fragment实例获取方式。
- 5.代码打包aar上传到
maven私人服务器
:
更多关于这个maven私服的信息,请参考这篇文章:
Gradle 基础(六)——使用 Maven 发布组件化类库
这里我们封装了一个通用的组件发布库:
应用插件:'maven'
上传档案{
存储库{
mavenDeployer {
// 是否快照版本
def isSnapShot = Boolean.valueOf(MAVEN_IS_SNAPSHOT)
def versionName = MAVEN_VERSION
if (isSnapShot) {
版本名称 += "-SNAPSHOT"
}
// 组件信息
pom.groupId = MAVEN_GROUP_ID
pom.artifactId = MAVEN_ARTIFACTID
pom.version = 版本名称
// 快照存储库路径
快照存储库(网址:uri(MAVEN_SNAPSHOT_URL)){
身份验证(用户名:MAVEN_USERNAME,密码:MAVEN_USERNAME)
}
// 发布仓库路径
存储库(网址:uri(MAVEN_RELEASE_URL)){
身份验证(用户名:MAVEN_USERNAME,密码:MAVEN_USERNAME)
}
println("#####################################"
+ "\nuploadArchives = " + pom.groupId + ":" + pom.artifactId + ":" + pom.version + "." + pom.包装
+ "\nrepository=" + (isSnapShot ? MAVEN_SNAPSHOT_URL : MAVEN_RELEASE_URL)
+ "\n####################################"
)
}
}
}
复制代码
然后在对应的组件下面引用它:
申请自:文件('../maven.gradle')
复制代码
直接在发布时 摇篮
在面板中单击 上传档案
任务
经过以上步骤,基本完成了登录组件的打包和发布,对外提供了登录组件接口。
其他组件也按照上述逻辑进行重构
更多详情可自行获取 项目源代码 查看。
5.组件化重构总结
组件化不仅是一种架构,更是一种理念。架构可以改变,但核心思想是统一的。拆分代码时要注意模块的粒度,并不是粒度越小越好。 ,模块分离良好,对后期的组件改造有很大帮助。
关于组件化的文章到此结束。组件化重构项目已上传至 Github。
以后会有 **插入**
项目改造。敬请关注。
版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议。转载请附上原文出处链接和本声明。
这篇文章的链接: https://homecpp.art/3704/6415/0928
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明
本文链接:https://www.qanswer.top/12250/57580411
标签:重构,ft,企业级,MAVEN,模块,组件,login From: https://www.cnblogs.com/amboke/p/16654789.html