小手动一动,点赞转发加关注。微信搜索【大前端杂货铺】公众号关注大前端老司机带您遨游大前端知识的海洋。关注 Github github.com/big-fronten… 还有大前端代码实践哦。
首页
bundles assembler 是一款编排bundle以此获取 构建速度/启动速度/内存占用/包体积 最大收益的项目
先定义一下bundle和foundation,bundle是依附于app framework的native bundle、flutter bundle、react native bundle、hybrid bundle,有些bundle具有动态性能被app framework动态加载;foundation是赋予上层能力的基础服务,更像是一些用来快速开发页面的toolkits,比如网络、存储、图像、音视频都是foundation。bundle之间相互解耦,bundle之间的通信主要有两种页面路由和rpc。
能力
声明了一些名词解释,我们来看看bundles assembler能提供怎么样的能力:
- 🚀 bundle多种加载方式:根据业务模块的重要性,可选择instant 、delay 、lazy 三种加载方式来优化构建速度/启动速度/内存占用等指标
- 📱 业务模块通讯IBC:自研IBC代码量少且容易使用
- ⌨️ 模块选择器:高效便捷的idea交互插件,让你像罗老师一样管理自己的各个小模块
- 免费maven仓库:提供免费的JamesfChen Snapshots(gradle.property文件 useJamesfChenSnapshots=true),让你免去费时费力搭建组件maven
- 📚高效工程化脚本:使用命令行轻松完成模板创建,项目脚手架初始化等工作
技术方案对比
| 框架 | JIMU | bundles-assembler |
|---|---|---|
| 工程脚手架 | × | √ |
| 模块选择idea插件 | × | √ |
| 模块加载 | 支持立即加载 | 支持立即/延迟/懒加载 |
| 模块发布 | 支持静态模块 | 支持静态模块/动态模块 |
| 支持多种路由库 | √ | √ |
| app集成方式 | jar/aar/source静态集成 | jar/aar/source/apk 动静结合集成 |
原理
对于bundle的加载方式有如下三种:
- bundle立即加载(instant load)
- bundle延迟加载(delay load)
- bundle懒加载(lazy load)
回顾一下插件化与组件化
| 解耦的方式 | 构建/执行 | 打包方式 |
|---|---|---|
| 组件化 | 编译时 | aar/jar |
| 插件化 | 运行时 | apk/dex |
先来说说立即加载,通过dexbuilder在编译期间将aar/jar的dex整合到app的dex中,然后经过art加载执行。 再来说说延迟加载 与 懒加载 ,两者的区别在于,前者会在MQ处于idle或者 draw end的阶段进行加载,不与界面的初始绘制抢夺cpu,后者使用时才会进行加载(在IBC接口调用时,才进行模块加载)。两者的共同点都是利用了插件化的技术实现,经由apkbuilder打包为apk,在安装加载时,会被extra出dex被ClassLoader加载 或者 直接被LoaderApk加载。
项目地址:bundles-assembler
快速入门
项目初始化
pip3 install bundcli
命令列表
通过bundcli init初始化项目模板工程
[1] % bundcli init --help
usage: command line init [-h] [-p PACKAGE] [-n NAME]
optional arguments:
-h, --help show this help message and exit
-p PACKAGE, --package PACKAGE 项目包名
-n NAME, --name NAME 项目名字
bundles-assembler-plugin
//app 模块
plugins{
id 'io.github.jamesfchen.app-plugin'
}
//foundation插件用于基础功能模块
plugins{
id 'io.github.jamesfchen.foundation-plugin'
}
创建模块
静态bundle
1.接入
bundcli可以创建bundle模板(native_static)
[0] % bundcli create --help
usage: command line create [-h] [-p PACKAGE] [-n PATH] [--type {none,flutter,reactnative,html5,native_stactic,native_dynimac}]
optional arguments:
-h, --help show this help message and exit
-p PACKAGE, --package PACKAGE 模块包名
-n PATH, --name PATH 模块名字
--type {none,flutter,reactnative,html5,native_stactic,native_dynimac} 模块类型
手动接入
module_config.json
{
"simpleName": "home-myhome",
"sourcePath": ":home-myhome",
"format": "nsbundle",
"group": "home"
}
bundles-assembler-plugin
//bundle插件自带路由,该插件主要用于bundle模块
plugins{
id 'io.github.jamesfchen.nsbundle-plugin'
}
//业务组件ibc中的cpbc 模块
plugins{
id 'io.github.jamesfchen.api-plugin'
}
2.静态bundle选择工具
集成app时,组件有三种状态
- source:源码形式集成
- binary:aar/jar包集成
- exclude:不集成
3.IBC
组件通信(IBC,inter-bundle communication)在解耦的模块中是一把利器,主要分为页面路由(Router)与接口调用(CBPC,cross bundle procedure call)
首先需要在app项目的build.gradle引入app-plugin插件
plugins{
id 'io.github.jamesfchen.app-plugin'
}
然后在bundle项目的build.gradle引入bundle-plugin插件
plugins{
id 'io.github.jamesfchen.nsbundle-plugin'
}
3.1.Router
- 利用android framework层的intent uri路由跳转
- 在app framework实现路由跳转,需要将app层的路由器发布到app framework的路由器管理中心,当需要跳转时,app framework会到管理中心find获取路由器,然后进行跳转
页面路由的实现有上面两种,任何一种都可以做到页面的跳转,两种方案各有优缺点。
首先提供路由页面的路由器,在编译的时候会自动将扫到的所有路由器注册到路由表。
@Router(bindingBundle = "bundle1")
class Bundle1Router : IRouter {
override fun onOpen(cxt: Context, page: String, params: Bundle?): Boolean {
if ("sayme".equals(page, ignoreCase = true)) {
val intent = Intent(cxt, SayMeActivity::class.java)
cxt.startActivity(intent)
return true
}
return false
}
}
接下来提供java和kotlin的使用
java
UriBuilder uriBuilder =new UriBuilder();
uriBuilder.setUri("b://bundle2/sayhi");
IBCRouter.open(SayMeActivity.this,uriBuilder);
kotlin
binding.btNative1.setOnClickListener {
// 打开当前bundle内部的页面
IBCRouter.open(this) {
uri = "/ppp"
}
}
binding.btNative2.setOnClickListener {
//打开当前bundle内部的页面
IBCRouter.open(this) {
uri = "b://bundle1/sayme"
}
}
binding.btReact.setOnClickListener {
//必须自定义router且bindingBundle=h5container
IBCRouter.open(this) {
uri = "https://spacecraft-plan.github.io/SpacecraftReact/#/"
params(
"key2" to "cjf2",
"key3" to 1,
"key4" to true
)
}
}
binding.btH5.setOnClickListener {
IBCRouter.open(this) {
uri = "b://h5container/page"
params(
"url" to "file:///android_asset/AApp.html",
)
}
}
binding.btRn.setOnClickListener {
IBCRouter.open(this) {
uri = "b://h5container/page"
params(
"url" to "file:///android_asset/AApp.html",
)
}
}
3.2.CBPC
- 暴露api给外部bundle模块,然后内部实现接口,需要在app framework注册暴露的api,方便search,实现方式与页面路由的第二种方法相似
在export模块的build.gradle需要引入api-plugin插件
plugins{
id "io.github.jamesfchen.api-plugin"
}
同时要声明要暴露的接口
abstract class ICall : IExport() {
abstract fun call():Boolean
}
callee模块
@Api
public class CallImp extends ICall{
@Override
public boolean call() {
Log.d("cjf","onCall");
return true;
}
}
caller模块
val api = IBCCbpc.findApi(ICall::class.java)
if (api.call()) {
...
}
callee模块与caller模块都要依赖export模块,且两者不能相互依赖。
动态bundle
插件包可以减少包体积也可以按需加载模块,功能多多
1.接入
cli命令行接入
bundcli可以创建动态bundle模板,该模板的初次加载方式有远程服务器加载与内置加载两种方式。
[0] % bundcli create --help
usage: command line create [-h] [-p PACKAGE] [-n PATH] [--type {none,flutter,reactnative,html5,native_stactic,native_dynimac}]
optional arguments:
-h, --help show this help message and exit
-p PACKAGE, --package PACKAGE 模块包名
-n PATH, --name PATH 模块名字
--type {none,flutter,reactnative,html5,native_stactic,native_dynimac} 模块类型
手动接入
module_config.json
{
"simpleName": "plugin-im",
"sourcePath": ":plugin-im",
"versionCode":"3",
"versionName":"3.0.0-SNAPSHOT",
"format": "ndbundle",
"group": "im",
"dynamic": "local-plugin"
},
bundles-assembler-plugin
plugins{
id 'io.github.jamesfchen.ndbundle-plugin'
}
2.动态bundle选择工具
- source:源码形式集成到apk
- binary:插件包以apk-zip/jsbundle包放置在assets或者远程服务器
- exclude:不集成
3.IBC
IBCRouter.open(this) {
uri = "b://im/nav"
}
通过IBC api就能进行通信,同静态bundle IBC使用方式一样
framework foundation模块
framework中的模块是为上层的业务模块提供基础能力,在项目中必须参与编译
1.接入
cli命令行接入
...
手动接入
{
"simpleName": "framework-network",
"sourcePath": ":framework:network",
"format": "foundation",
"group": "fwk"
},
bundles-assembler-plugin
plugins{
id 'io.github.jamesfchen.foundatioin-plugin'
}
2. foundation选择工具
- source:源码形式集成到apk
- binary:aar形式
小手动一动,点赞转发加关注。微信搜索【大前端杂货铺】公众号关注大前端老司机带您遨游大前端知识的海洋。关注 Github github.com/big-fronten… 还有大前端代码实践哦。