组件化开发的思路是:
把项目的各个模块用library形式抽取出来,每个模块负责自己的业务,在开发阶段,各个模块可以单独打包成apk运行。最终的项目用一个壳application把这些library模块整合到一起,可以输出一个完整的apk。
组件化的实现步骤:
1.项目根目录创建一个文件“config.gradle”:
ext {
isModule = true
}
2.项目根目录的build.gradle中引用刚刚创建的"config.gradle":
//实现赋值与引用
apply from: 'config.gradle'
buildscript {
//....
}
到这一步,就是告诉gradle的rootProject(项目根目录的build.gradle就会被翻译成为rootProject),添加一个字典isModule = true 。
3.创建一个lib module项目”module1“。
4.修改module1 的build.gradle文件(module的build.gradle也会被翻译成为project,每个project都会持有rootProject对象,可以引用rootProject的属性):
apply plugin: 'com.android.library'
为
if (isModule) {
apply plugin: 'com.android.library'
} else {
apply plugin: 'com.android.application'
}
这样,当修改isModule后,重新编译,module1就会按照 library或者application 的方式加到项目中,为library就说明它是一个库,为application就说明它是可打包apk的app项目。
5.在壳项目”app“中修改build.gradle:
dependencies {
if(isModule){
implementation project(path: ':module1')
}
}
效果是:当module1以application方式运行时,壳app就不去依赖module1。
到这里,我们就可以通过修改”confi.gradle"来切换"module1"的工作方式。
补充:
”module1“作为application运行时,必须要告诉它的AndroidManifest.xml 指明一个LAUNCHER入口:
<activity android:name=".XXXXXX">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
但是作为lib运行时,我们没有这个要求。因此,”module1“需要根据isModule来指定不同的AndroidManifest.xml文件。
lib运行时,src/main/AndroidManifest.xml 写成:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="carlwu.top.module1">
//...
</manifest>
application运行时,src/cmp/AndroidManifest.xml 写成:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="carlwu.top.module1">
<application
android:theme="@style/Theme.AppCompat.Light.DarkActionBar">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
我们可以在module1 的build.gradle文件中加上这样的配置:
android {
//...
sourceSets {
main {
if (!isModule) {
manifest.srcFile 'src/cmp/AndroidManifest.xml'
}
}
}
}
告诉编译器,application方式运行module1时,加载符合application运行要求的AndroidManifest.xml文件。
有时我们把module1当成application运行时,需要指定自定义的Application类,那么就需要把src/cmp/AndroidManifest.xml 这么写:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="carlwu.top.module1">
<application
android:name=".MyApplication"//指定自定义的Application
android:theme="@style/Theme.AppCompat.Light.DarkActionBar">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
我们就需要在module1的java目录下添加MyApplication这个类,但是如果不做处理,module1当lib被app依赖也会把类MyApplication依赖进去,这个类实际上是不需要被依赖的,最好是编译都不要参与。我们是有办法的。
修改module1的build.gradle:
android {
//...
sourceSets {
main {
if (!isModule) {
java.srcDirs 'src/cmp/java'
manifest.srcFile 'src/cmp/AndroidManifest.xml'
}
}
}
}
意思就是告诉编译器,module1除了默认的src/main/java 目录外,还可以添加 src/cmp/java 这个目录最为源码目录,里面的类也会参与编译打包。
效果如下: