Android组件化开发实践笔记
一、什么是组件化和插件化?
组件化和插件化组件化开发就是将一个app分成多个模块,每个模块都是一个组件(Module),开发的过程中我们可以让这些组件相互依赖或者单独调试部分组件等,但是最终发布的时候是将这些组件合并统一成一个apk,这就是组件化开发。
插件化开发和组件化开发略有不用,插件化开发时将整个app拆分成很多模块,这些模块包括一个宿主和多个插件,每个模块都是一个apk(组件化的每个模块是个lib),最终打包的时候将宿主apk和插件apk分开或者联合打包。
(一)组件化
1,概述
android工程的组件一般分为两种,library组件和application组件
application组件是指该组件本身就可以运行并打包成apk
library组件是指该组件属于app的一部分,可以供其它组件使用但是本身不能打包成apk
2,为什么要有组件化?
加入一个app工程只有一个组件,随着app业务的壮大模块越来越多,代码量超10万是很正常的,这个时候我们会遇到以下问题:
* 稍微改动一个模块的一点代码都要编译整个工程,耗时耗力
* 公共资源、业务、模块混在一起耦合度太高
* 不方便测试
3,如何组件化?
名词解释 图片.png这是组件化工程模型下的业务关系,业务之间将不再直接引用和依赖,而是通过“路由”这样一个中转站间接产生联系,而Android中的路由实际就是对URL Scheme的封装。
4,组件化实践流程
1)如何实现组件模式和集成模式的转换?
Android Studio中的Module主要有两种属性,分别为:
(1)、application属性,可以独立运行的Android程序,也就是我们的APP;
apply plugin: ‘com.android.application’
(2)、library属性,不可以独立运行,一般是Android程序依赖的库文件;
apply plugin: ‘com.android.library’
Module的属性是在每个组件的 build.gradle 文件中配置的,当我们在组件模式开发时,业务组件应处于application属性,这时的业务组件就是一个 Android App,可以独立开发和调试;而当我们转换到集成模式开发时,业务组件应该处于 library 属性,这样才能被我们的“app壳工程”所依赖,组成一个具有完整功能的APP。
Gradle自动构建工具有一个重要属性,可以帮助我们完成这个事情。每当我们用AndroidStudio创建一个Android项目后,就会在项目的根目录中生成一个文件 gradle.properties,我们将使用这个文件的一个重要属性:在Android项目中的任何一个build.gradle文件中都可以把gradle.properties中的常量读取出来;那么首先我们在gradle.properties中定义一个常量值 isModule(是否是组件开发模式,true为是,false为否):
# 每次更改“isModule”的值后,需要点击 "Sync Project" 按钮
isModule=false
然后我们在业务组件的build.gradle中读取 isModule,但是 gradle.properties 还有一个重要属性: gradle.properties 中的数据类型都是String类型,使用其他数据类型需要自行转换;也就是说我们读到 isModule 是个String类型的值,而我们需要的是Boolean值,代码如下:
if (isModule.toBoolean()) {
apply plugin: 'com.android.application'
} else {
apply plugin: 'com.android.library'
}
这样我们第一个问题就解决了,注意每次改变isModule的值后,都要同步项目才能生效。
2)组件之间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呢?
但是大家应该注意到这个问题是在组件开发模式和集成开发模式之间转换引起的问题,而在上一节中我们已经解决了组件模式和集成模式转换的问题,这样解决办法也就有了,我们可以为组件开发模式下的业务组件再创建一个 AndroidManifest.xml,然后根据isModule指定AndroidManifest.xml的文件路径,让业务组件在集成模式和组件模式下使用不同的AndroidManifest.xml,这样问题就可以规避了。
业务组件目录结构在业务组件的 build.gradle 中指定表单的路径,代码如下:
sourceSets {
main {
if (isModule.toBoolean()) {
manifest.srcFile 'src/main/module/AndroidManifest.xml'
} else {
manifest.srcFile 'src/main/AndroidManifest.xml'
}
}
}
首先是集成开发模式下的 AndroidManifest.xml,前面我们说过集成模式下,业务组件的表单是绝对不能拥有自己的 Application 和 launch 的 Activity的,也不能声明APP名称、图标等属性,总之app壳工程有的属性,业务组件都不能有,下面是一份标准的集成开发模式下业务组件的 AndroidManifest.xml:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.guiying.girls">
<application android:theme="@style/AppTheme">
<activity
android:name=".main.GirlsActivity"
android:screenOrientation="portrait" />
<activity
android:name=".girl.GirlActivity"
android:screenOrientation="portrait"
android:theme="@style/AppTheme.NoActionBar" />
</application>
</manifest>
&emsp然后是组件开发模式下的表单文件:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.guiying.girls">
<application
android:name="debug.GirlsApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/girls_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".main.GirlsActivity"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".girl.GirlActivity"
android:screenOrientation="portrait"
android:theme="@style/AppTheme.NoActionBar" />
</application>
</manifest>
3)如何在 APP 工程添加依赖具体业务组件 Module?
在app壳工程 的 build.gradle文件中设置:
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
annotationProcessor "com.github.mzule.activityrouter:compiler:$rootProject.annotationProcessor"
if (isModule.toBoolean()) {
compile project(':lib_common')
} else {
compile project(':module_main')
compile project(':module_girls')
compile project(':module_news')
}
}
4)如何管理组件?
在Android组件化方案中,由于所有组件都在同一个项目中,并且使用 compile project(‘:组件名’) 方式依赖其他组件,这样就会导致很多问题。
1. 编译很慢。
2. 组件不方便引用。
3. 无法控制权限,也不方便混淆。
一般开源库都是上传到maven或jcenter仓库上供我们引用。那么我们自己开发的组件能不能传到maven或jcenter仓库呢?当然了。不是让你传到开源仓库上去,我们可以在公司内部搭建一个私有的maven仓库,将开发好的组件上传到这个私有的maven仓库上,然后内部开发人员就可以像引用三方库那样轻而易举的将组件引入到项目中了,这是他们关系就像下图这样:
图片.png
(二)插件化
1,为什么有插件化?
有了组件化,为什么还要用插件化呢?插件化开发总的来说有以下几点好处(不同插件框架不一样):
* 宿主和插件分开编译
* 并发开发
* 动态更新插件
* 按需下载模块
* 方法数或变量数爆棚
2,开源的插件化框架
* Qihoo360/DroidPlugin
* CtripMobile/DynamicAPK
* wequick/Small
* VirtualAPK