家政客服露露姐 發表於 2019-11-28 14:16:00

Android 插件化开发(四):插件化实现方案

<p>在经过上面铺垫后,我们可以尝试整体实现一下插件化了。这里我们先介绍一下最简单的实现插件化的方案。</p>
<h2>一、最简单的插件化实现方案</h2>
<p>最简单的插件化实现方案,对四大组件都是适用的,技术面涉及如下:</p>
<p>1). 合并所有插件的Dex,来解决插件的类的加载问题。</p>
<p>2). 预先在宿主的AndroidManifest.xml文件中声明插件的四大组件。(如果插件组件过多会很麻烦)</p>
<p>3). 把插件中的所有资源一次性的合并到宿主的资源中。(合并时可能会导致id冲突)</p>
<p>使用此组件化方案实现时,Service、ContentProvider 和 Receiver 只要合并 dex 就够了,因为这些没有资源访问的概念。</p>
<p>但是Activity插件化实现时就会比较麻烦,因为Activity严重依赖资源,想实现Activity的插件化就必须解决加载插件中资源的问题。</p>
<p>在&nbsp;Android 插件化开发(三):资源插件化&nbsp;中我们介绍过AssetsManager和Resource这两个类的关系,AssetManager有一个addAssetPath方法,可以一次性把插件的路径都导入,然后再生成一个含有全局资源的Resource,以后无论查找插件还是宿主的的资源都能找到了。</p>
<p>虽然此方案能实现插件化,但是此方案有很大的问题:</p>
<p>1.&nbsp;插件的四大组件要事先声明,无法动态新增,这样对于Activity来说是无法兼容的问题(其他组件相对问题较少)。</p>
<p>2. 资源id会冲突。</p>
<p>3. 无法预料插件内Activity,对于插件内动态新增的Activity无法进行使用。</p>
<p>项目代码仓库地址:https://github.com/renhui/RHPluginProgramming/tree/master/ZeusStudy</p>
<p>了解如何实现一个最简单的插件化之后,我们再整理一下Activity如何实现插件化。这里单独再提一下 Activity 是因为 Activity 是 App 中使用频率最高的组件,所以这里我们先讲述一下Activity的插件化。</p>
<p>Activity 的插件化需要解决3方面的技术问题:</p>
<p>1). 宿主App可以加载App中的类。</p>
<p>2). 宿主App可以加载App中的资源。</p>
<p>3). 宿主App可以加载插件中的Activity。</p>
<p>前两个技术问题,我们已解决了,这里我们讲一下第3个的技术问题的解决方案。主要的解决方案有很多种,这里只简单以两个有标志性的框架:</p>
<p>a. 以DroidPlugin框架为代表的动态替换方案,提供对Android底层的各类进行Hook,以达到插件化中的四大组件的目的。</p>
<p>b. 以DynamicLoadApk框架为代表的静态代理方案,通过ProxyActivity统一加载插件中的所有Activity。</p>
<p>&nbsp;</p>
<p>下面我们再讲一下DynamicLoadApk框架,此框架在《Android插件化开发指南》书中重点提及了,本人也比较感兴趣。</p>
<h2>三、DynamicLoadApk 插件化框架</h2>
<p>DynamicLoadApk 是一个开源的 Android 插件化框架。</p>
<p>插件化的优点包括:(1) 模块解耦,(2) 动态升级,(3) 高效并行开发(编译速度更快) (4) 按需加载,内存占用更低等等。</p>
<p>DynamicLoadApk 提供了 3 种开发方式,让开发者在无需理解其工作原理的情况下快速的集成插件化功能。</p>
<ol>
<li>宿主程序与插件完全独立;</li>
<li>宿主程序开放部分接口供插件与之通信;</li>
<li>宿主程序耦合插件的部分业务逻辑。</li>
</ol>
<h3>1. DynamicLoadApk 框架核心概念</h3>
<p>(1) 宿主:主 App,可以加载插件,也称 Host。</p>
<p>(2) 插件:插件 App,被宿主加载的 App,也称 Plugin,可以是跟普通 App 一样的 Apk 文件。</p>
<p>(3) 组件:指 Android 中的Activity、Service、BroadcastReceiver、ContentProvider,目前 DL 支持Activity、Service以及动态的BroadcastReceiver。</p>
<p>(4) 插件组件:插件中的组件。</p>
<p>(5) 代理组件:在宿主的 Manifest 中注册,启动插件组件时首先被启动的组件。目前包括 DLProxyActivity(代理 Activity)、DLProxyFragmentActivity(代理 FragmentActivity)、DLProxyService(代理 Service)。</p>
<p>(6) Base 组件:插件组件的基类,目前包括 DLBasePluginActivity(插件 Activity 的基类)、DLBasePluginFragmentActivity(插件 FragmentActivity 的基类)、DLBasePluginService(插件 Service 的基类)。</p>
<p>DynamicLoadApk 原理的核心思想可以总结为两个字:代理。通过在 Manifest 中注册代理组件,当启动插件组件时首先启动一个代理组件,然后通过这个代理组件来构建、启动插件组件。</p>
<h3>2. DynamicLoadApk 框架设计思路</h3>
<p><img src="https://img2018.cnblogs.com/blog/682616/201911/682616-20191128092246478-2122214588.png" alt="" width="600"></p>
<p>上面是 DynamicLoadApk 的总体设计图,DynamicLoadApk 主要分为四大模块:</p>
<p>(1) DLPluginManager</p>
<p>插件管理模块,负责插件的加载、管理以及启动插件组件。</p>
<p>(2) Proxy</p>
<p>代理组件模块,目前包括 DLProxyActivity(代理 Activity)、DLProxyFragmentActivity(代理 FragmentActivity)、DLProxyService(代理 Service)。</p>
<p>(3) Proxy Impl</p>
<p>代理组件公用逻辑模块,与(2)中的 Proxy 不同的是,这部分并不是一个组件,而是负责构建、加载插件组件的管理器。这些 Proxy Impl 通过反射得到插件组件,然后将插件与 Proxy 组件建立关联,最后调用插件组件的 onCreate 函数进行启动。</p>
<p>(4) Base Plugin</p>
<p>插件组件的基类模块,目前包括 DLBasePluginActivity(插件 Activity 的基类)、DLBasePluginFragmentActivity(插件 FragmentActivity 的基类)、DLBasePluginService(插件 Service 的基类)。</p>
<h3>3.&nbsp;DynamicLoadApk 流程说明</h3>
<p><img src="https://img2018.cnblogs.com/blog/682616/201911/682616-20191128092550397-175973656.png" alt="" width="600"></p>
<p>上面是调用插件 Activity 的流程图,其他组件调用流程类似。</p>
<p>(1) 首先通过 DLPluginManager 的 loadApk 函数加载插件,这步每个插件只需调用一次。</p>
<p>(2) 通过 DLPluginManager 的 startPluginActivity 函数启动代理 Activity。</p>
<p>(3) 代理 Activity 启动过程中构建、启动插件 Activity。</p>
<h2>四、其他的插件化解决方案</h2>
<p>在介绍其他的插件化解决方案之前,我们先看一下插件化技术的演进图:</p>
<p><img src="https://img2018.cnblogs.com/blog/682616/201911/682616-20191128140316868-2055499320.png" alt="" width="800"></p>
<p>&nbsp;以下是相关的项目地址:</p>
<div>
<p>1) 携程:https://github.com/CtripMobile/DynamicAPK</p>
<p>2) 奇虎:https://github.com/Qihoo360/DroidPlugin</p>
<p>3) 任玉刚: https://github.com/singwhatiwanna/dynamic-load-apk</p>
<p>4) Dynamic Loader:https://github.com/mmin18/AndroidDynamicLoader</p>
<p>5) 滴滴:https://github.com/didi/VirtualAPK</p>
<p>6) 360:https://github.com/Qihoo360/RePlugin</p>
</div>
<p>7) Small:https://github.com/wequick/Small</p>
<p>&nbsp;</p>
<p>虽然插件化的相关框架不少,但是核心技术还是不变的,那就是:<span style="color: rgba(255, 0, 0, 1)"><strong>反射 + 代理</strong></span>。</p>
<p>&nbsp;</p><br><br>
来源:https://www.cnblogs.com/renhui/p/11930115.html
頁: [1]
查看完整版本: Android 插件化开发(四):插件化实现方案