插件化之DynamicLoadApk原理解析
背景:
插件化技术主要是解决apk体积、内存、cpu占用逐渐增大问题,实现热插拔(即在不发版的情况下更新app的功能)。
通过插件化还可以实现模块之间解耦,并行开发,提高apk编译速度。
什么是插件化:
ANDROID插件化是指将整个APP按照模块拆分,每个模块以插件的形式组装成一个APP。要实现插件化必需要理解另
外一个概念—组件化。组件是指工程内通用性和复用行较高的模块以及相对独立的功能模块。比如,网络框架、图片
缓存、PASSPORT等都可以作为一个组件集成到工程内,从而实现公共模块的复用以及模块之间的解耦。
组件化是插件化的前提,只有实现了工程结构的组件化才能实现插件化,从而可以实现模块以插件的形式集成到工程中,
也可以实现模块动态更新修复bug或者发布小版本。
插件化的优缺点:
优点:
1.模块解耦,模块之间耦合度降低,提高代码的复用度。
2.解决单个dex方法数65535的限制。
3.动态升级,修复bug或者小版本升级不需要发版,对于部分新功能可以解除版本之间的限制。
4.并行开发(提高编译、开发速度)
5.主app的体积减小,部分插件在需要的时候动态下载。
缺点:
1.大部分插件化方案是通过hook底层方法实现,存在机型兼容性问题。
2.目前插件化技术方案不完善导致在生产环境下会遇到各种坑。
DynamicLoadApk原理解析:
在详细讲解DynamicLoadApk之前先了解一下插件化中比较重要的两个概念:宿主、插件。
宿主:指主app,可以称之为host,宿主可以加载插件,是整个app的入口。
插件:插件app,被宿主加载的app,可以跟普通app一样被安装单独运行。
插件化宿主和插件的组织关系: 通过上图我们可以看到宿主和插件的关系,插件依赖于宿主,宿主可以加载多个插件。
宿主可以调用插件但插件不可以调用宿主。
插件化宿主和插件的组织关系:
image2016-10-2712-52-8.png通过上图我们可以看到宿主和插件的关系,插件依赖于宿主,宿主可以加载多个插件。宿主可以调用插件但插件不可以调用宿主。
框架设计:
image2016-10-2712-52-31.png整体的框架主要包括四个部分:
DLPluginManager:插件管理模块,负责插件的加载、管理以及启动、解绑插件组件。下图是DLPluginManager加载插件的流程:
Proxy:代理组件模块,目前包括 DLProxyActivity(代理 Activity)、DLProxyFragmentActivity(代理 FragmentActivity)、DLProxyService(代理 Service)。
Proxy Impl代理组件公用逻辑模块,与(2)中的 Proxy 不同的是,这部分并不是一个组件,而是负责构建、加载插件组件的管理器。这些 Proxy Impl
通过反射得到插件组件,然后将插件与 Proxy 组件建立关联,最后调用插件组件的 onCreate 函数进行启动。
Base Plugin插件组件的基类模块,目前包括 DLBasePluginActivity(插件 Activity 的基类)、DLBasePluginFragmentActivity(插件 FragmentActivity
的基类)、DLBasePluginService(插件 Service 的基类)。
宿主调用插件的流程:
image2016-10-2712-53-9.png上面是调用插件 Activity 的流程图,其他组件调用流程类似。
(1) 首先通过 DLPluginManager 的 loadApk 函数加载插件,这步每个插件只需调用一次。
(2) 通过 DLPluginManager 的 startPluginActivity 函数启动代理 Activity。
(3) 代理 Activity 启动过程中构建、启动插件 Activity。
总结:
以上是DynamicLoadApk的整体框架和实现原理,该框架hook底层代码比较少使用代理模式实现插件中Android四大组件的使用,相比其它框架系统兼容性问题比较少。