Android 插件化开发(四):插件化实现方案
在经过上面铺垫后,我们可以尝试整体实现一下插件化了。这里我们先介绍一下最简单的实现插件化的方案。
一、最简单的插件化实现方案
最简单的插件化实现方案,对四大组件都是适用的,技术面涉及如下:
1). 合并所有插件的Dex,来解决插件的类的加载问题。
2). 预先在宿主的AndroidManifest.xml文件中声明插件的四大组件。(如果插件组件过多会很麻烦)
3). 把插件中的所有资源一次性的合并到宿主的资源中。(合并时可能会导致id冲突)
使用此组件化方案实现时,Service、ContentProvider 和 Receiver 只要合并 dex 就够了,因为这些没有资源访问的概念。
但是Activity插件化实现时就会比较麻烦,因为Activity严重依赖资源,想实现Activity的插件化就必须解决加载插件中资源的问题。
在 Android 插件化开发(三):资源插件化 中我们介绍过AssetsManager和Resource这两个类的关系,AssetManager有一个addAssetPath方法,可以一次性把插件的路径都导入,然后再生成一个含有全局资源的Resource,以后无论查找插件还是宿主的的资源都能找到了。
虽然此方案能实现插件化,但是此方案有很大的问题:
1. 插件的四大组件要事先声明,无法动态新增,这样对于Activity来说是无法兼容的问题(其他组件相对问题较少)。
2. 资源id会冲突。
3. 无法预料插件内Activity,对于插件内动态新增的Activity无法进行使用。
项目代码仓库地址:https://github.com/renhui/RHPluginProgramming/tree/master/ZeusStudy
了解如何实现一个最简单的插件化之后,我们再整理一下Activity如何实现插件化。这里单独再提一下 Activity 是因为 Activity 是 App 中使用频率最高的组件,所以这里我们先讲述一下Activity的插件化。
Activity 的插件化需要解决3方面的技术问题:
1). 宿主App可以加载App中的类。
2). 宿主App可以加载App中的资源。
3). 宿主App可以加载插件中的Activity。
前两个技术问题,我们已解决了,这里我们讲一下第3个的技术问题的解决方案。主要的解决方案有很多种,这里只简单以两个有标志性的框架:
a. 以DroidPlugin框架为代表的动态替换方案,提供对Android底层的各类进行Hook,以达到插件化中的四大组件的目的。
b. 以DynamicLoadApk框架为代表的静态代理方案,通过ProxyActivity统一加载插件中的所有Activity。
下面我们再讲一下DynamicLoadApk框架,此框架在《Android插件化开发指南》书中重点提及了,本人也比较感兴趣。
三、DynamicLoadApk 插件化框架
DynamicLoadApk 是一个开源的 Android 插件化框架。
插件化的优点包括:(1) 模块解耦,(2) 动态升级,(3) 高效并行开发(编译速度更快) (4) 按需加载,内存占用更低等等。
DynamicLoadApk 提供了 3 种开发方式,让开发者在无需理解其工作原理的情况下快速的集成插件化功能。
- 宿主程序与插件完全独立;
- 宿主程序开放部分接口供插件与之通信;
- 宿主程序耦合插件的部分业务逻辑。
1. DynamicLoadApk 框架核心概念
(1) 宿主:主 App,可以加载插件,也称 Host。
(2) 插件:插件 App,被宿主加载的 App,也称 Plugin,可以是跟普通 App 一样的 Apk 文件。
(3) 组件:指 Android 中的Activity、Service、BroadcastReceiver、ContentProvider,目前 DL 支持Activity、Service以及动态的BroadcastReceiver。
(4) 插件组件:插件中的组件。
(5) 代理组件:在宿主的 Manifest 中注册,启动插件组件时首先被启动的组件。目前包括 DLProxyActivity(代理 Activity)、DLProxyFragmentActivity(代理 FragmentActivity)、DLProxyService(代理 Service)。
(6) Base 组件:插件组件的基类,目前包括 DLBasePluginActivity(插件 Activity 的基类)、DLBasePluginFragmentActivity(插件 FragmentActivity 的基类)、DLBasePluginService(插件 Service 的基类)。
DynamicLoadApk 原理的核心思想可以总结为两个字:代理。通过在 Manifest 中注册代理组件,当启动插件组件时首先启动一个代理组件,然后通过这个代理组件来构建、启动插件组件。
2. DynamicLoadApk 框架设计思路
上面是 DynamicLoadApk 的总体设计图,DynamicLoadApk 主要分为四大模块:
(1) DLPluginManager
插件管理模块,负责插件的加载、管理以及启动插件组件。
(2) Proxy
代理组件模块,目前包括 DLProxyActivity(代理 Activity)、DLProxyFragmentActivity(代理 FragmentActivity)、DLProxyService(代理 Service)。
(3) Proxy Impl
代理组件公用逻辑模块,与(2)中的 Proxy 不同的是,这部分并不是一个组件,而是负责构建、加载插件组件的管理器。这些 Proxy Impl 通过反射得到插件组件,然后将插件与 Proxy 组件建立关联,最后调用插件组件的 onCreate 函数进行启动。
(4) Base Plugin
插件组件的基类模块,目前包括 DLBasePluginActivity(插件 Activity 的基类)、DLBasePluginFragmentActivity(插件 FragmentActivity 的基类)、DLBasePluginService(插件 Service 的基类)。
3. DynamicLoadApk 流程说明
上面是调用插件 Activity 的流程图,其他组件调用流程类似。
(1) 首先通过 DLPluginManager 的 loadApk 函数加载插件,这步每个插件只需调用一次。
(2) 通过 DLPluginManager 的 startPluginActivity 函数启动代理 Activity。
(3) 代理 Activity 启动过程中构建、启动插件 Activity。
四、其他的插件化解决方案
在介绍其他的插件化解决方案之前,我们先看一下插件化技术的演进图:
以下是相关的项目地址:
1) 携程:https://github.com/CtripMobile/DynamicAPK
2) 奇虎:https://github.com/Qihoo360/DroidPlugin
3) 任玉刚: https://github.com/singwhatiwanna/dynamic-load-apk
4) Dynamic Loader:https://github.com/mmin18/AndroidDynamicLoader
7) Small:https://github.com/wequick/Small
虽然插件化的相关框架不少,但是核心技术还是不变的,那就是:反射 + 代理。
Android 插件化开发(四):插件化实现方案的更多相关文章
- 从零开始实现ASP.NET Core MVC的插件式开发(四) - 插件安装
标题:从零开始实现ASP.NET Core MVC的插件式开发(四) - 插件安装 作者:Lamond Lu 地址:https://www.cnblogs.com/lwqlun/p/11260750. ...
- 从零开始实现ASP.NET Core MVC的插件式开发(五) - 插件的删除和升级
标题:从零开始实现ASP.NET Core MVC的插件式开发(五) - 使用AssemblyLoadContext实现插件的升级和删除 作者:Lamond Lu 地址:https://www.cnb ...
- Android 音视频开发(四):使用 Camera API 采集视频数据
本文主要将的是:使用 Camera API 采集视频数据并保存到文件,分别使用 SurfaceView.TextureView 来预览 Camera 数据,取到 NV21 的数据回调. 注: 需要权限 ...
- 从零开始实现ASP.NET Core MVC的插件式开发(八) - Razor视图相关问题及解决方案
标题:从零开始实现ASP.NET Core MVC的插件式开发(八) - Razor视图相关问题及解决方案 作者:Lamond Lu 地址:https://www.cnblogs.com/lwqlun ...
- 从零开始实现ASP.NET Core MVC的插件式开发(六) - 如何加载插件引用
标题:从零开始实现ASP.NET Core MVC的插件式开发(六) - 如何加载插件引用. 作者:Lamond Lu 地址:https://www.cnblogs.com/lwqlun/p/1171 ...
- 从零开始实现ASP.NET Core MVC的插件式开发(七) - 近期问题汇总及部分解决方案
标题:从零开始实现ASP.NET Core MVC的插件式开发(七) - 问题汇总及部分解决方案 作者:Lamond Lu 地址:https://www.cnblogs.com/lwqlun/p/12 ...
- 从零开始实现ASP.NET Core MVC的插件式开发(九) - 升级.NET 5及启用预编译视图
标题:从零开始实现ASP.NET Core MVC的插件式开发(九) - 如何启用预编译视图 作者:Lamond Lu 地址:https://www.cnblogs.com/lwqlun/p/1399 ...
- Android组件化和插件化开发
http://www.cnblogs.com/android-blogs/p/5703355.html 什么是组件化和插件化? 组件化开发就是将一个app分成多个模块,每个模块都是一个组件(Modul ...
- 插件化开发—动态加载技术加载已安装和未安装的apk
首先引入一个概念,动态加载技术是什么?为什么要引入动态加载?它有什么好处呢?首先要明白这几个问题,我们先从 应用程序入手,大家都知道在Android App中,一个应用程序dex文件的方法数最大不能超 ...
- 插件化开发—动态载入技术载入已安装和未安装的apk
首先引入一个概念,动态载入技术是什么?为什么要引入动态载入?它有什么优点呢?首先要明确这几个问题.我们先从 应用程序入手,大家都知道在Android App中.一个应用程序dex文件的方法数最大不能超 ...
随机推荐
- CTF比赛时准备的一些shell命令
防御策略: sudo service apache2 start :set fileformat=unix1.写脚本关闭大部分服务,除了ssh 2.改root密码,禁用除了root之外的所 ...
- java JDK安装包的获取与安装
Java JDK 安装包获取和安装: JDK 1.8.211 官网下载地址 https://www.oracle.com/technetwork/java/javase/downloads/jdk8- ...
- JavaScript-----2初识
1.介绍 JavaScript是一种运行在客户端(自己的电脑上)的脚本语言不是在服务器上 脚本语言:不需要编译,运行过程由JS解释器(js引擎)逐行进行解释并执行 JavaScript不仅可以做前端编 ...
- 启动项目报错:org.apache.catalina.LifecycleException: Failed to start component
原因 环境异常重启,项目java进程未关闭,原项目的端口依旧在占用. 一般为8080端口被占用 解决方法 以下两种方法都可以解决,原理相同(结束异常进程) 1. 简单粗暴: 打开任务管理器找到java ...
- Qt之高DPI显示器(二) - 自适配解决方案分析
目录 一.回顾 二.框架说明 1.ICallDPIChanged 2.IDPIHelper 3.悬浮窗体管理器 三.方案分析 1.窗口大小 2.字体大小 3.间距 4.图标 四.相关文章 原文链接:Q ...
- 上手spring boot项目(一)之如何在controller类中返回到页面
题记:在学习了springboot和thymeleaf之后,想完成一个项目练练手,于是使用springboot+mybatis和thymeleaf完成一个博客系统,在完成的过程中出现的一些问题,将这些 ...
- python数据挖掘第一篇:正则表达式
正则表达式 re 模块 re.match(pattern,string[,flag]) match方法 从首字母开始匹配,如果包含pattern字符串,则匹配成功,返回match对象,失败则返回Non ...
- 用JS实现HTML转PDF
遇到这个需求,现把实现代码整理出来,方便大家参考 <!-- html转PDF --> <script src="https://cdnjs.cloudflare.com/a ...
- rsync服务的讲解
第2章 rsync备份服务器的搭建 2.1 rsync备份服务器的概念 2.1.1 概念 rsync服务器对网站服务器数据进行备份(防止数据丢失和数据进行恢复) rsync服务器对网站服务器数据进行对 ...
- tensorflow mnist模块详解
tensorflow的官方文档是以mnist数据集为例子开始的.文档本身没有介绍tensorflow.contrib.learn.python.learn.datasets.mnist模块.要想用te ...