为什么要模块化/组件化

跟着APP版别不断的迭代,新功用的不断增加,事务也会变的越来越复杂,APP事务模块的数量有或许还会持续增加,而且每个模块的代码也变的越来越多,这样发展下去单一工程下的APP势必会影响开发功率,增加项目的保护本钱,每个工程师都要熟悉如此之多的代码,将很难进行多人协作开发

Android 组件化架构思路
上图是现在比较遍及运用的Android APP技能架构,往往是在一个界面中存在很多的事务逻辑, 整个项目中也没有模块的概念,只要简略的以事务逻辑区分的文件夹,而且事务之间也是直接彼此调用、高度耦合在一起的;

模块化/组件化的区分

经过对项目事务跟功用,能够先对项目中的事务和功用进行区分,拆成独立的模块跟组件。如下图,简略对咱们项目进行区分拆分事务跟组成,经过组件化的方法依靠到宿主app中,终究对立成一个终究的app项目。

Android 组件化架构思路

  • app壳工程:负责办理各个事务组件,和打包apk,没有具体的事务功用;
  • 事务组件:依据公司具体事务而独立构成一个的工程;
  • 根底组件:提供开发APP的根底功用,比如说网络结构
  • 功用组件:集成的一些第三方sdk,独立成library,提供给各事务组件运用
  • 集成形式: 一切的事务组件被“app壳工程”依靠,组成一个完好的APP
  • 组件形式: 能够独立开发事务组件,每一个事务组件就是一个APP;

怎么组件化实施流程

(1)组件形式和集成形式的转化 咱们知道android studio中的module有两种特点,分别为

application特点

apply plugin: ‘com.android.application’

library特点

apply plugin: ‘com.android.library’

当咱们在组件形式开发时,事务组件应处于application特点,而当咱们转化到集成形式开发时,事务组件应该处于 library 特点;

怎么转化?

在项目的gradle.properties文件中装备,isModule特点

# 是否为插件形式,true则各组件可独立运行,打包时需改成false
isModule=false

在事务组件build.gradle文件中经过以下装备决定当前组件是组件形式仍是集成形式。

if (isModule.toBoolean()) {
    apply plugin: 'com.android.application'
} else {
    apply plugin: 'com.android.library'
}

组件化中会遇到的问题

组件之间AndroidManifest兼并问题

在 AndroidStudio 中每一个组件都会有对应的 AndroidManifest.xml,用于声明需求的权限、Application、Activity、Service、Broadcast等,当项目处于组件形式时,事务组件的 AndroidManifest.xml 应该具有一个 Android APP 所具有的的一切特点,尤其是声明 Application 和要 launch的Activity,可是当项目处于集成形式的时分,每一个事务组件的 AndroidManifest.xml 都要兼并到“app壳工程”中,要是每一个事务组件都有自己的 Application 和 launch的Activity,那么兼并的时分肯定会抵触,试想一个APP怎么或许会有多个 Application 和 launch 的Activity呢?

咱们需求在build.gradle 中指定下 AndroidManifest.xml 的位置,AndroidStudio 才干读取到 AndroidManifest.xml,这样处理办法也就有了,咱们可认为组件开发形式下的事务组件再创立一个 AndroidManifest.xml,然后依据isModule指定AndroidManifest.xml的文件途径,让事务组件在集成形式和组件形式下运用不同的AndroidManifest.xml,这样表单抵触的问题就能够规避了。

Android 组件化架构思路

上图是组件化项目中一个标准的事务组件目录结构,首要咱们在main文件夹下创立一个module文件夹用于寄存组件开发形式下事务组件的 AndroidManifest.xml,而 AndroidStudio 生成的 AndroidManifest.xml 则依然保存,并用于集成开发形式下事务组件的表单;然后咱们需求在事务组件的 build.gradle 中指定表单的途径,代码如下:

//设置了resourcePrefix值后,一切的资源名有必要以指定的字符串做前缀,不然会报错。
//可是resourcePrefix这个值只能限制xml里边的资源,并不能限制图片资源,一切图片资源依然需求手动去修正资源名。
resourcePrefix "user_"
sourceSets {
    main {
        jniLibs.srcDirs = ['libs']
        if (isModule.toBoolean()) {
            manifest.srcFile 'src/main/module/AndroidManifest.xml'
        } else {
            manifest.srcFile 'src/main/AndroidManifest.xml'
            java {
                exclude 'debug/**'
            }
        }
    }
}

组件之间通讯问题

在组件化开发的时分,组件之间是没有依靠联系,咱们不能在运用显现调用来跳转页面了,这儿咱们引入阿里的路由结构处理组件之间的通讯问题,这儿采用的原理是运用apt技能依据注解生成对应的源码,完结跳转。 以下是Arouter的官方地址

github.com/alibaba/ARo…

library依靠问题

1:重复依靠 假如A组件跟B组件都依靠了C组件,D组成同时依靠了A,B组件,这时分就会导致重复依靠C组件的问题,此刻能够经过exlude特点去除重复依靠问题

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile("com.jude:easyrecyclerview:$rootProject.easyRecyclerVersion") {
        exclude module: 'support-v4'//依据组件名排除
        exclude group: 'android.support.v4'//依据包名排除
    }
}

2:透传依靠 假如A组成依靠了B组成,B组件依靠了C组件,此刻咱们假如想在A,B组成中都用C组件里边的功用能够经过api依靠的方法,向上透传

//fastjson
api deps.fastjson_android

资源重复命名问题

比如说咱们或许在A,B组件中同时创立了相同姓名的文件,这时分打包就会出问题,这时分咱们需求对资源文件的命名有一定的标准,通常需求咱们在gradle文件中做如下装备

//设置了resourcePrefix值后,一切的资源名有必要以指定的字符串做前缀,不然会报错。
//可是resourcePrefix这个值只能限制xml里边的资源,并不能限制图片资源,一切图片资源依然需求手动去修正资源名。
resourcePrefix "user_"

Android 组件化架构思路
如上图:通常咱们会在组件的资源文件中会以组件的姓名作为前缀开端命名

项目混杂问题

组件化项目的Java代码混杂计划采用在集成形式下集中在app壳工程中混杂,各个事务组件不装备混杂文件。集成开发形式下在app壳工程中build.gradle文件的release构建类型中敞开混杂特点,其他buildTypes装备计划跟普通项目保持一致,Java混杂装备文件也放置在app壳工程中,各个事务组件的混杂装备规矩都应该在app壳工程中的混杂装备文件中增加和修正。

之所以不采用在每个事务组件中敞开混杂的计划,是因为 组件在集成形式下都被 Gradle 构建成了 release 类型的arr包,一旦事务组件的代码被混杂,而这时分代码中又呈现了bug,将很难依据日志找出导致bug的原因;别的每个事务组件中都保存一份混杂装备文件非常不便于修正和办理,这也是不推荐在事务组件的 build.gradle 文件中装备 buildTypes (构建类型)的原因。

组件化/模块化项目结构图

Android 组件化架构思路

总结

项目模块化需求对项目整体进行把控,事务的区分,功用模块的抽取,以及适宜的架构计划跟技能选型,这都需求花费很多精力,任重而道远。