前言
Small官网: https://github.com/wequick/Small
世界那么大,组件那么小。Small,做最轻巧的跨平台插件化框架。 ——Galenlin
这是Small作者,林光亮老师,给Small一句概括。
今年6月份,我和同事Simon奔赴北京参加 GMTC全球移动技术大会2016。当时Galenlin给大家介绍了Small插件化框架,插件化加载dex、资源拆分、hook.....
Dynamic-load-apk的作者任玉刚也有演讲,不过没介绍DLA。
回广州后,对Small做了几个实验性demo,不禁赞叹Small真的非常简洁,而且基本能满足 APP组件化需求。
Small完成什么使命?
组件化,既熟悉又陌生的词汇。通俗点说,就是把APP拆分成不同功能模块,形成独立组件,让宿主调用。
组件化不一定是插件化,组件化是一个更大的概念:把模块解耦,组件之间代码不依赖,宿主可以依赖组件;而插件化则具体到了技术点上,宿主通过 动态加载 来调用组件,宿主不依赖组件,达到 完全解耦 的目的。
Small插件化方案适用于将一个APK拆分为多个公共库插件、业务模块插件的场景。
(知乎上一个插件化提问《怎么将 Android 程序做成插件化的形式?》)
框架对比
Android插件化框架有很多,相信Dynamic-load-apk、ACDD、DroidPlugin 如雷贯耳。
Small官方比较:COMPARISION.md
DyLA : Dynamic-load-apk @singwhatiwanna, 百度
DiLA : Direct-Load-apk @FinalLody
APF : Android-Plugin-Framework @limpoxe
ACDD : ACDD @bunnyblue
DyAPK : DynamicAPK @TediWang, 携程
DPG : DroidPlugin @cmzy, 360
功能
/DyLADiLAACDDDyAPKDPGAPFSmall加载非独立插件[1]×x√√×√√加载.so后缀插件××! [2]×××√Activity生命周期√√√√√√√Service动态注册××√×√√x [3]资源分包共享[4]××! [5]! [5]×! [6]√公共插件打包共享[7]××××××√支持AppCompat[8]××××××√支持本地网页组件××××××√支持联调插件[9]×x××××√
Small初体验
1.Create Project
假设宿主包名为com.example.mysmall
设置Application name为MySmall修改Company Domain为mysmall.example.com
create project.png
2.配置build.gradle
对project/build.gradle修改如下:
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.1.2'
classpath 'net.wequick.tools.build:gradle-small:1.0.0-beta3'
}
}
apply plugin: 'net.wequick.small'
small {
aarVersion = '1.1.0-beta1'
}
...
(com.android.tools.build:gradle用回你Android Studio支持的gradle插件版本)
aarVersion、net.wequick.tools.build:gradle-small版本号,可以参照Small官方sample的build.gradle。sample
3.新建Application
new SmallApp
public class SmallApp extends Application {
@Override
public void onCreate() {
super.onCreate();
Small.preSetUp(this);
Small.setBaseUri("http://example.com/");// 浏览器跳转url
Small.setUp(this, null);
// Small.setUp(this, new Small.OnCompleteListener(){...});
}
}
AndroidManifest.xml:
android:name=".SmallApp" ... > 4.新建 插件Module File->New->Module,选择Phone & Tablet Module: Application Name: App.mainModule name: app.mainpackage name: com.example.mysmall.app.main 如果选择Android Library,app.*换成lib.* new module app.main.png Small要求插件module满足: 模块名形如:app.* , lib.* 或者web.*包名包含:.app., .lib.或者.web. Add an Activity to Mobile选择最简单的Empty Activity即可(其他也可以)。 除了默认MainActivity,顺手创建多个ActivityB吧。 5.配置UI route 新建assets/bundle.json: { "version": "1.0.0", "bundles": [ { "uri": "main", "pkg": "com.example.mysmall.app.main", "rules": { "page2": ".ActivityB" } } ] } uri : 跳转Activity需要的uripkg : 插件模块包名rules : 指定跳转的Activity Small/UI-route 6.跳转到插件Activity @Override public void onClick(View view) { Small.openUri("main", this); // open bundles.main Launch Activity // Small.openUri("main/page2", context);// 指定跳转到app.main.page2 } 调用openUri后,就可以跳转到插件的某个Activity了。 7.编译插件 1)Build libraries (准备基础库) gradlew buildLib buildLib_appmain.gif 如果插件module是Android Library,这时会生成app/smallLibs/armeabi/*.so 2)Build bundles (打包所有组件) gradlew buildBundle buildBundle_appmain.gif 生成app/smallLibs/armeabi/libcom_example_mysmall_app_main.so so文件.png 运行 由于project有两个Phone & Tablet Module,运行时要选app噢 5 - run config.png 使用效果 你会发现,宿主app没有依赖app.main,仅仅把app.main编译成so文件, 宿主app就可以跳转到插件app.main页面了。这就是插件化的魅力——零依赖! 遇到的问题 之前遇到一个很奇葩的问题,如图: some error 解决方法: gradlew cleanLibbradlew cleanBundle重新buildLib、buildBundle即可 还试过运行时提示“找不到app/MainActivity”,解决:File->Invalidate Caches/Restart清一下缓存再重启AS就好了。 小结 Small算是最简单的插件化框架,如果你的project本来就已经组件化到一定程度,使用Small轻而易举。 由于笔者还未试过在实际项目中使用,可能有些潜在的坑未踩。Small的更新也是蛮积极的,目前大概一个月更新一次,在交流Q群&issue,Galenlin回应也很积极。 强烈建议大家看看Small Issue,了解大家在使用中遇到的问题,以及Galenlin和其他人提出的解决方案。目前就4页,中文的,不会太多哈哈。 笔者相信,未来半年一年,Small会更稳定、更容易在项目中集成,让我们更爽地体验插件化的优势! Small Demo Git 推荐阅读: 携程Android App插件化和动态加载实践Android插件化:从入门到放弃 作者:键盘男 链接:https://www.jianshu.com/p/7990714d10cb 來源:简书 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。