概述
单独开发每个模块,用集成的方式把他们组合起来,拼出一个app。如通用的模块,自动更新的模块,反馈模块,推送模块都可以单独以模块来开发,最后进行集成。我们可以通过一个壳来包含很多个模块。
好处
可以单独升级模块。耦合度低。同时,也很好地解决了“牵一发而动全身”的问题。方便分工。与其他团队合作时,如外包的团队,可以很好的地将核心代码与外包部分隔离开,不用和他们分享核心代码,让他们去做独立的功能,做好直接调用就行。方便以后重构代码,不用担心会改到核心代码。
架构分层
- 顶层:
将所有的业务模块聚合在一起,加上配置,形成主应用。一个模块化做得好的应用,主应用都会比较简单且稳定。 - 中间层:
模块按照功能划分。比如app可以划分为更新、登录、分享、播放等模块。采用aar作为模块的最小单位,之所以选择aar是因为jar不能带资源只能带java代码,library太容易被修改。aar的好处是能带资源并且是编译好的,不能被修改。保证了模块的版本不会在被别人调用的时候随意修改,如果想修改就要联系做aar的人,让他去升级aar的版本。
在android studio里,用maven打包aar。aar其实就是依赖。 - 底层:包含基础库和底层库
(1)基础库:包含所有模块需要的依赖库,以及一些工具类,比如封装了的常用网络请求,封装图片处理fresco,数据库相关等,还包含所有模块需要的依赖库;
(2)底层库:主要是使用C/C++开发的跨平台的引擎或者库,以so的形式存在。
Android Studio 项目结构
- MyApplication 整个项目目录
- MyApplication/build.gradle是整个项目的gradle构建脚本
- MyApplication/gradle.properties是整个项目的gradle设置
- MyApplication/MyApplication.iml是整个项目的配置文件
- MyApplication/settings.gradle是定义整个项目包含哪些模块
- app项目中app模块目录
- app/build/是app模块build编译输出的目录
- app/app.iml是app模块的配置文件
- app/.gitignore是app模块的版本管理忽略文件
- app/build.gradle是app模块的gradle构建脚本
- app/proguard-rules.pro是app模块的混淆文件
- External Libraries 项目依赖的Lib,编译时自动下载的
Android Studio 新建的项目自身就是一个模块化项目。因为MyApplication 是整个项目,而app是一个模块。可以在后续自行增加更多的功能模块。
在Android Studio进行模块化开发
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')
}
模块中 application 和 library 状态切换配置
组件化和插件化是两个不同的概念。插件化作用在“运行时”,而组件化作用在“编译时”。插件化是基于多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')
}
}
这样就完成了。
Android 模块化开发过程中可能遇到的问题
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
谢谢阅读
来源:CSDN
作者:WongKyunban
链接:https://blog.csdn.net/weixin_40763897/article/details/103801287