单独开发每个模块,用集成的方式把他们组合起来,拼出一个app。如通用的模块,自动更新的模块,反馈模块,推送模块都可以单独以模块来开发,最后进行集成。我们可以通过一个壳来包含很多个模块。
可以单独升级模块。耦合度低。同时,也很好地解决了“牵一发而动全身”的问题。方便分工。与其他团队合作时,如外包的团队,可以很好的地将核心代码与外包部分隔离开,不用和他们分享核心代码,让他们去做独立的功能,做好直接调用就行。方便以后重构代码,不用担心会改到核心代码。
Android Studio 新建的项目自身就是一个模块化项目。因为MyApplication 是整个项目,而app是一个模块。可以在后续自行增加更多的功能模块。
1.创建 Module 模块
有两种方式。
方式一:针对已存在的模块,只需要将模块复制到项目的根目录(如上面的MyApplication目录)下即可。这种方式需要在根目录下的setting.gradle文件中设置一下,格式:
include ':projectName'
方式二:直接在project下新建一个Module。操作步骤:
File --> New --> New Module --> Android Library (建议选择这个) --> Finish
这种方式会自动在根目录下的setting.gradle文件中设置。
在主模块app模块的build.gradle中设置:
dependencies {
...
implementation project(path: ':modulea')
}
组件化和插件化是两个不同的概念。插件化作用在“运行时”,而组件化作用在“编译时”。插件化是基于多APK,而组件化本质上只有一个APK。
(1)用一个属性来控制gradle构建插件的切换。 如果我们创建的Module是要作为一个库library来给别的模块使用,那么就应该使用com.android.library这个gradle插件来构建。如果我们Module是一个应用,而不是插件,那么就要使用com.android.application这个gradle插件来构建。我们可以在gradle.properties文件(在根目录下)来配置一些属性,然后在各个Module的build.gradle的构建脚本里就可以根据这属性来判断要使用哪个插件,如:
gradle.properties
# false表示是集成化开发模式,true表示是组件化开发模式
isModule = false
isModule = false:表示这个模块是一个Module(插件);
isModule = true:表示这个模块是一个app(组件);
(2)在模块的build.gradle文件中使用isModule属性。
在modulea模块的build.gradle中使用isModule来判断要使用哪个构建脚本插件:
if(isModule.toBoolean()){
apply plugin: 'com.android.application'
}else{
apply plugin: 'com.android.library'
}
android {
...
defaultConfig {
...
// library下删除applicationId
// 如果是组件就要给一个applicationId
if(isModule.toBoolean()){
applicationId "com.wong.modulea"
}
}
...
}
(3)提供两套 AndroidManifest.xml并进行动态切换
android {
...
sourceSets {
main{
// 应用
if(isModule.toBoolean()){
manifest.srcFile 'src/main/buildApp/AndroidManifest.xml'
}else{// 插件
manifest.srcFile 'src/main/buildModule/AndroidManifest.xml'
}
}
}
}
(组件)src/main/buildApp/AndroidManifest.xml的内容可能如下:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.wong.modulea" >
<application>
<activity android:name=".WarehouseActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
</manifest>
(插件)src/main/buildModule/AndroidManifest.xml的内容可能如下:
buildModule 的 AndroidManifest.xml, activity 等在这里可以正常注册。这里注册后主程序就可以不用写了。
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.wong.modulea">
<application>
<activity android:name=".WarehouseActivity"></activity>
</application>
</manifest>
(4)在app模块的build.gradle配置如下:
dependencies {
...
if(!isModule.toBoolean()){
implementation project(path: ':modulea')
}
}
这样就完成了。
1.资源名冲突
默认情况, library 的所有的 resource 为 public , 在模块化开发过程中很容易遇到资源冲突问题。两种解决方法:
(1)保护某些 resources 不被外部访问,通过创建res/values/public.xml来完成,至少添加一行,就会被视为 private。
<resources>
<public name="mylib_app_name" type="string"/>
</resources>
(2)在 library 的 build.gradle 中添加 resourcePrefix , 则所有的资源须以此 prefix 开头,否则报错。注意,图片资源虽然不提示报错误,但是也需要修改名字。
android {
...
buildTypes {
...
}
resourcePrefix 'my_prefix_'
}
2.依赖重复
解决方法:将所有的依赖都写在library层的module里,将所有的依赖统一一个入口给顶层的app用。
最后送上demo
谢谢阅读