架构设计之插件化、组件化
组件化方案
1、module library 切换
2、组件间跳转uri跳转
3、组件间通讯 binder机制
主工程(壳工程mudele)
不分配任何具体业务逻辑。用于使用组合业务组件、初始化配置和发布应用配置等
组件(module/library)
实现具体业务逻辑,尽可能保证业务独立性。具体根据自己的项目需要来划分
公共库(library)
公共使用的工具类、sdk等库,如eventbus、xutils、rxandroid、自定义工具类等等,可做公共csdk、也可以实现抽离很细按照需求依赖使用
两种模式
测试模式:组件是独立module模式,module可以独立运行,只要保证他对其他业务没有依赖就可以独立开发测试
发布模式:组件是library模式被主工程依赖组合,发布运行,所有业务将组合成完整app发布运行
问题
模式间如何自由切换?
1 //工程根目录下的gradle.properties文件(其中的值作为String常亮给项目中的各个build.gradle共享)中配置
isPlugin=false
2 //moudle的build.gradle文件中(首行)配置
if (isPlugin.toBoolean()) { //将String类型转换成boolean类型
apply plugin: 'com.android.application' //固定写法,作为一个module进行编译
} else {
apply plugin: 'com.android.library' //固定写法,作为一个library进行编译
}
3 //moudle的build.gradle文件中,包名的配置(作为library时,不需要包名)
defaultConfig {
if (isPlugin.toBoolean()){ //包名配置栏,增加标志判断
applicationId 'com.example.rspluginmodule'
}
....
}
4 //处理AndroidManifest.xml文件,因为library、module的清单文件有区别
//在指定文件夹(最好是工程目录下)下创建AndroidManifest.xml,如src/main/test/AndroidManifest.xml
//因此,上述AndroidManifest文件作为测试模式的清单文件,默认的作为发布模式的清单文件
默认library、module的清单文件对比
<!-- library -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.mylibrary" />
<!-- module -->
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.mymoudle">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<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>
各moudle间如何跳转?
使用Intent跳转,如
<!-- 定义意图 -->
<intent-filter>
<data
android:host="sijienet"
android:path="/plugin_uri_path"
android:scheme="app_schem" />
<action android:name="cn.com.bailian.plugin.VIEW_ACTION" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<!-- 跳转 -->
Intent intent=new Intent(RMConfig.ROUTER_URL_ACTION, Uri.parse(url));
intent.addCategory(Intent.CATEGORY_DEFAULT);
intent.putExtra(RMConfig.ROUTER_PARM, parm);
PackageManager packageManager=activity.getPackageManager();
List<ResolveInfo> resolveInfos = packageManager.queryIntentActivities(intent, 0);
if (! resolveInfos.isEmpty()){
activity.startActivity(intent);
}
组件间如何通信?
首选进程通讯机制(IPC),案例见Code案例——BInder通信
插件化
优点
1、业务组件解耦合,实现业务组件热拔插
2、更改迭代模式,由整个APP发版模式变成APP发版和业务插件发版流程
3、不更新APP版本即可BUG修复和业务组件升级等热修复功能
4、插件化建立在组件化架构之上,包含组件化所有优点
应用场景
1、项目一些偏向UI界面具有更新要求快的模块
2、activity为主,大部分框架对activity支持较好
3、对so等第三方库依赖较少,so对插件化兼容性稳定考验比较大
4、项目未使用AOP切面编程
市面上插件化框架
DyLA | DiLA | ACDD | DyAPK | DPG | APF | Small | |
---|---|---|---|---|---|---|---|
加载非独立插件 | Y | Y | Y | Y | |||
加载.so后缀插件 | Y | ||||||
Activity生命周期 | Y | Y | Y | Y | Y | Y | Y |
Service动态注册 | Y | Y | Y | N | |||
资源分包共享 | Y | ||||||
公共插件打包共享 | Y | ||||||
支持AppCompat | Y | ||||||
支持本地网页组件 | Y | ||||||
支持联调插件 | Y |