版权声明:本文为博主原创文章,未经博主允许不得转载。
本篇文章只是整理了一些流行的开源插件化技术,其中言论纯属开源作者,不代表本人观点。
完美内置
所有插件支持内置于宿主包中
高度透明
插件编码、布局编写方式与独立应用开发无异
插件代码调试与整包开发无异
极致剪裁
对插件分离所有一切能分离的公共代码、资源
无缝链接
通过设定URI,宿主、本地化应用插件、本地化web插件、在线网页,以及任何自定义的插件之间能够相互调起与传递参数
跨平台
目前已支持Android、iOS以及html5插件。并且三者之间可以通过同一套javascript接口进行通信。
二、Small Android(支持平台:Android API 15(4.0.3))
各个插件框架功能对比:
DyLA : Dynamic-load-apk @singwhatiwanna, 百度 DiLA : Direct-Load-apk @melbcat APF : Android-Plugin-Framework @limpoxe ACDD : ACDD @bunnyblue DyAPK : DynamicAPK @TediWang, 携程 DPG : DroidPlugin @cmzy, 360
功能
\ DyLA DiLA ACDD DyAPK DPG APF Small 加载非独立插件[1] × x √ √ × √ √ 加载.so插件 × × ! [2] × × × √ Activity生命周期 √ √ √ √ × √ √ Service动态注册 × × √ × × √ x [3] 资源分包共享[4] × × ! [5] ! [5] × ! [6] √ 公共插件打包共享[7] × × × × × × √ 支持AppCompat[8] × × × × × × √ 支持本地网页组件 × × × × × × √ 支持联调插件[9] × x × × × × √
[1] 独立插件:一个完整的apk包,可以独立运行。比如从你的程序跑起淘宝、QQ,但这加载起来是要闹哪样?
非独立插件:依赖于宿主,宿主是个壳,插件可使用其资源代码并分离之以最小化,这才是业务需要嘛。
-- “所有不能加载非独立插件的插件化框架都是耍流氓”。[2] ACDD加载.so用了Native方法(libdexopt.so),不是Java层,源码似乎未共享。
[3] Service更新频度低,可预先注册在宿主的manifest中,如果没有很好的理由说服我,现不支持。
[4] 要实现宿主、各个插件资源可互相访问,需要对他们的资源进行分段处理以避免冲突。
[5] 这些框架修改aapt源码、重编、覆盖SDK Manager下载的aapt,我只想说“杀(wan)鸡(de)焉(kai)用(xin)牛(jiu)刀(hao)”。
Small使用gradle-small-plugin,在后期修改二进制文件,实现了PP段分区。[6] 使用public-padding对资源id的TT段进行分区,分开了宿主和插件。但是插件之间无法分段。
[7] 除了宿主提供一些公共资源与代码外,我们仍需封装一些业务层面的公共库,这些库被其他插件所依赖。
公共插件打包的目的就是可以单独更新公共库插件,并且相关插件不需要动到。[8] AppCompat: Android Studio默认添加的主题包,Google主推的Metrial Design包也依赖于此。大势所趋。
[9] 联调插件:使用Android Studio调试宿主时,可直接在插件代码中添加断点调试。
透明度
\ ACDD DyAPK APF Small 插件Activity代码无需修改 √ √ √ √ 插件引用外部资源无需修改name × × × √ 插件模块无需修改build.gradle × x × √
Step 1. Clone Small (下载源码)
> cd [你要放Small的目录] > git clone https://github.com/wequick/Small.git
强烈建议使用git命令行,方便更新维护。Windows用户入口:Git for Windows
后续更新可以使用命令:git pull origin master
Step 2. Import Sample project (导入示例工程)
打开Android Studio,File->New->Import Project... 选择Sample文件夹,导入。
Sample
示例工程
app
宿主工程
app.*
包含Activity/Fragment的组件
lib.*
公共库组件
web.*
本地网页组件
sign
签名文件
顺便说下,这些app.*跟web.*可以从工具栏的按钮单独运行。
其中app.home无法单独运行是因为它只包含一个Fragment,没有Launcher Activity。
Step 3. Build libraries (准备基础库)
> [./]gradlew buildLib -q (-q是安静模式,可以让输出更好看,也可以不加)
Step 4. Build bundles (打包所有组件)
> [./]gradlew buildBundle -q (-q是安静模式,可以让输出更好看,也可以不加)
Step 5. Import DevSample project (导入开发工程)
打开Android Studio,File->New->Import Project... 选择DevSample文件夹,导入。
DevSample
开发工程
buildSrc
组件编译插件,用于打包组件
small
核心库,用于加载组件
buildSrc在修改后会被自动编译。
其他步骤同上。除了编译单个组件的命令有所不同:
> [./]gradlew :app.main:assembleRelease
P.s. gradlew命令支持缩写,比如
assembleRelease
可以缩写为aR
四、实现Android插件化的核心技术:
五、常见问题 FAQ
插件是否一定得内置到APK中,如果一定要内置,那这个框架仅仅是为了开发工程中解耦?
内置是为了首次启动更快,如果不内置也行,可以在启动页下载插件。
目前开源的插件开发框架有很多,Small 跟这些框架的区别是什么,优缺点呢?
把核心代码量控制在了一个文件(ApkBundleLauncher)500行以内
不修改aapt源码,实现了资源id PP段的再分配(原理见Dynamic load resources)
通过对aapt生成的二进制文件的后期加工,最大化分离无用的资源,使得插件包最小达到4k左右
支持对本地化网页进行插件打包,实现跨平台
dynamic-load-apk使用代理的方式实现Activity生命周期,插件中不能用this,不够透明;
Direct-Load-apk对dynamic-load-apk进行了改进,支持this。但也是用代理Activity,实现较为繁琐;
Android-Plugin-Framework是一个相对完整的框架,但资源分区方案还不够理想,不支持加载.so插件;
ACDD 使用了osgi,没有细看。。坑点是资源分区要使用修改aapt源码再重新编译的方案;
DynamicAPK 坑点:修改aapt源码,不支持.so插件;
DroidPlugin支持对完整apk的动态加载,但是没有关于非独立插件的加载(资源分区要复杂得多);
这些框架似乎都不支持AppCompat包(但这很重要,材料设计的Design包等都依赖AppCompat);
Small的开发其实是跟随1、2、3走过来的。从实际场景出发,基于“轻量、透明、极小化、跨平台”的理念:
百度工程师开发的 Dynamic-load-apk
melbcat开源的 Direct-Load-apk
limpoxe开源的 Android-Plugin-Framework
bunnyblue开源的 ACDD
携程工程师开发的 DynamicAPK
360工程师开发的 DroidPlugin
顶
0
踩
0