photo-1441716844725-09cedc13a4e7.jpg
前言
世界那么大,组件那么小。Small,做最轻巧的跨平台插件化框架。 ——Galenlin
这是Small作者,林光亮老师,给Small一句概括。
今年6月份,我和同事Simon奔赴北京参加 GMTC全球移动技术大会2016。当时Galenlin给大家介绍了Small插件化框架,插件化加载dex、资源拆分、hook.....
回广州后,对Small做了几个实验性demo,不禁赞叹Small真的非常简洁,而且基本能满足 APP组件化需求。
Small完成什么使命?
组件化,既熟悉又陌生的词汇。通俗点说,就是把APP拆分成不同功能模块,形成独立组件,让宿主调用。
组件化不一定是插件化,组件化是一个更大的概念:把模块解耦,组件之间代码不依赖,宿主可以依赖组件;而插件化则具体到了技术点上,宿主通过 动态加载 来调用组件,宿主不依赖组件,达到 完全解耦 的目的。
Small插件化方案适用于将一个APK拆分为多个公共库插件、业务模块插件的场景。
框架对比
Android插件化框架有很多,相信Dynamic-load-apk、ACDD、DroidPlugin 如雷贯耳。
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
功能
/
DyLA
DiLA
ACDD
DyAPK
DPG
APF
Small
加载非独立插件[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.main
Module name: app.main
package 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需要的uri
pkg : 插件模块包名
rules : 指定跳转的Activity
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 cleanLib
bradlew cleanBundle
重新buildLib、buildBundle即可
还试过运行时提示“找不到app/MainActivity”,解决:File->Invalidate Caches/Restart清一下缓存再重启AS就好了。
小结
Small算是最简单的插件化框架,如果你的project本来就已经组件化到一定程度,使用Small轻而易举。
由于笔者还未试过在实际项目中使用,可能有些潜在的坑未踩。Small的更新也是蛮积极的,目前大概一个月更新一次,在交流Q群&issue,Galenlin回应也很积极。
强烈建议大家看看Small Issue,了解大家在使用中遇到的问题,以及Galenlin和其他人提出的解决方案。目前就4页,中文的,不会太多哈哈。
笔者相信,未来半年一年,Small会更稳定、更容易在项目中集成,让我们更爽地体验插件化的优势!
推荐阅读:
关于转载
如果你想转载此文,请务必在转载时,加上原文作者&原文链接。谢谢