Atlas是阿里巴巴在淘宝不断演化中在Android系统上推出的一个容器化框架,也叫动态组件化(Dynamic Bundle)框架。它主要提供了解耦化、组件化、动态性的支持。覆盖了工程师的工程编码期、Apk运行期以及后续运维期的各种问题。
在工程期,实现工程独立开发,调试的功能,工程模块可以独立。
在运行期,实现完整的组件生命周期的映射,类隔离等机制。
在运维期,提供快速增量的更新修复能力,快速升级。
Atlas是工程期和运行期共同起作用的框架,我们尽量将一些工作放到工程期,这样保证运行期更简单,更稳定。快速开发的同时,能够进行灵活发布,动态更新以及提供了线上故障快速修复的能力。
与点评,360的插件框架不同的是,atlas是一个组件框架,atlas不是一个多进程的框架,主要完成的就是在运行环境中按需地去完成各个bundle的安装,加载类和资源。
技术术语
Bundle: 类似OSGI规范里面bundle(组件)的概念,每个bundle有自己的classloader,与其他bundle相隔离,同时Atlas框架下bundle有自身的资源段(PackageID,打包时AAPT指定);另外与原有OSGI所定义的service格式不同之处是Atlas里面Bundle透出所有定义在Manifest里面的component,随着service,activity的触发执行bundle的安装,运行。
awb: android wireless bundle的缩写,实际上同AAR类似,是最终构建整包前的中间产物。每个awb最终会打成一个bundle。awb与aar的唯一不同之处是awb与之对应有个packageId的定义。
host: 宿主的概念,所有的bundle可以直接调用host内的代码和资源,所以host常常集合了公共的中间件,UI资源等。host和bundle的依赖关系如下图所示:
host: 宿主的概念,所有的bundle可以直接调用host内的代码和资源,所以host常常集合了公共的中间件,UI资源等。host和bundle的依赖关系如下图所示:
框架剖析
从上图也可以看出基于Atlas构建后大致工程的结构:
首先有个构建整体APK工程Apk_builder,里面管理着所有的依赖(包括atlas)及其版本,Apk_builder本身可能不包含任何代码,只负责构建使用 host内部包含独立的中间件,以及一个Base的工程,里面可能包含应用的Application,应用icon等基础性内容(如果足够独立,application也可以直接放在apk_builder内); 业务层基本上以bundle为边界自上而下与host发生调用,同时bundle之间允许存在依赖关系;相对业务独立的bundle如果存在接口耦合建议封装成aidl service的方式保证自身封装性;同时某些中间件如果只存在若干bundle使用的也可以封装bundle的方式提供出来,以保证host内容精简
remote bundle: 远程bundle,远程bundle只是apk构建时并未打到apk内部,而是单独放在了云端;同时远程bundle的限制条件是第一次被触发的前提是bundle内的Activity需要被start,此时基于Atlas内的ClassNotFoundInterceptorCallback可以进行跳转的重定向,提示用户下载具体bundle,待用户确定后进行异步下载同时完成后再跳转到目标bundle(此部分代码由于涉及下载及UI展示等内容并未包含在开源仓库中,有需要可以根据ClassNotFoundInterceptorCallback自行实现)
APK结构
基于Atlas构建后的APK结构如下图,host与普通Apk无异,但是Manifest和assets会添加一些额外的内容,同时在armeabi目录中会增加若干个bundle构建的产物,取名为String.format(lib%s.so,packagename.replace(".","_"));packagename为bundle的AndroidManifest中的packagename,这些so都是正常的apk结构,改为so放入lib目录只是为了安装时借用系统的能力从apk中解压出来,方便后续安装
原理剖析
如上图所示,atlas主要分为以下几个层级:
另外内置的原生的multidex在dalvik上面性能并不好,atlas内部对其进行了优化提高了在dalvik上面的体验。
除AtlasBridgeApplication之外,接入层对外提供了部分工具类,包括主动install bundle,start bundle,以及获取全局的application等各种功能。
每个bundle的生命周期如下图所示:
Installed bundle被安装到storage目录
Resolved classloader被创建,assetpatch注入DelegateResoucces
Active bundle的安全校验通过;bundle的dex检测已经成功dexopt(or dex2oat),resource已经成功注入
Started bundle开始运行,bundle application的onCreate方法被调用
Atlas里面通常会创建了两种classLoader,第一个是DelegateClassLoader,他作为类查找的一个路由器而存在,本身并不负责真正类的加载;DelegateClassLoader启动时被atlas注入LoadedApk中,替换原有的PathClassLoader;第二个是BundleClassLoader,参考OSGI的实现,每个bundle resolve时会分配一个BundleClassLoader,负责该bundle的类加载。关系如下图所示: DelegateClassLoader以PathClassLoader为parent,同时在路由过程中能够找到所有bundle的classloader;
BundleClassLoader以BootClassLoader为parent,同时引用PathClassLoader,BundleClassLoader自身findClass的顺序为
1. findOwn: 查找bundle dex 自身内部的class
2. findDependency: 查找bundle依赖的bundle内的class
3. findPath: 查找主apk中的class
示列
下图是容器中类加载的大致顺序; 可以认为是一个Bundle的Activity启动的类加载过程来帮助理解(假设Activity所在的bundle已经安装);
类似ClassLoader,LoadedApk中的Resources被替换成Atlas内部的DelegateResources,同时在每个Bundle安装的过程中,每个bundle的assetspath会被更新到DelegateResources的AssetsManager中;每个bundle的资源特征如图可知:
更新原理
通Apk的更新的过程为构建->安装->生效,与之相对应,动态部署也可以分为三个过程:
官方GitHub:https://github.com/alibaba/atlas 素材和技术均来自atlas官网。
技术 - 资讯 - 感悟
END