Android插件化开发之动态加载的类型

https://segmentfault.com/a/1190000005113493

基本信息

  • Author:kaedea

  • GitHub:android-dynamical-loading

现在网络上有许多关于动态加载的介绍的文章,谈及的关键词汇有动态加载、插件化、热部署、热修复等,对于一些刚接触这方面开发技术的人来说,可能容易混淆。

虽然我在动态加载系列的文章中或多或少有谈到这些概念的区别,但是我觉得认识这些区别对于使用动态加载技术还是挺重要的,所以特别开这个新的文章进行分析。

动态加载的类型

无论是插件化、热部署还是热修复,这些技术的根源都可是说是动态加载,这也是我把“动态加载”作为这个系列文章主题的原因。

动态加载,就是在程序运行时,加载外部的可执行文件并运行。这里的运行时就是指应用冷启动并开始工作后;外部可以是可以是SD卡,可以是data目录,也可以是jniLib目录,这些可执行文件是没有随着应用一起编译的。

Android的动态加载按照工作机制的不同,可以分为虚拟机层动态加载和Native层动态加载两大类。

运行在虚拟机

简单来说就是只用JAVA代码搞定的类型。

基于虚拟机的动态加载技术的核心是类加载器ClassLoader,通过它我们能够加载一些新的类,这种方式也是目前大部分技术文章谈到的加载方式。其中,根据ClassLoader使用方式的不同,又演变出“热部署”、“插件化”、“热修复”等技术。

热部署

加载外部可执行文件的ClassLoader实例与原APP的ClassLoader实例是互相独立的(不在同一棵代理树上),加载进来的新的类与原APP(宿主)里存在的类互相独立,根据Java对类的定义,因为这些类的ClassLoader不同,所以他们即便包名和类名一致,或者有继承关系,他们也属于不懂的类。所以以这种方式加载进来的类与原有的类不能互通,不能污染宿主原有的类,适合用来动态加载一些独立的业务,比如一些推广的游戏,在宿主上提供一个入口,用户不需要安装游戏就能运行。因为这种方式起到不用安装就能部署游戏的作用,所以称为热部署。

插件化

加载外部可执行文件的ClassLoader实例与宿主的ClassLoader实例不是互相独立的,用宿主的ClassLoader加载过的类就无法从外部可执行文件中再次加载,它们可以共用一个公共库,习惯上把外部可执行文件称为插件。插件里可以存放公共库里一些借口的实现类,可以有一些新的Activity或者Service等组件,可以把一些宿主里的业务挪到插件中,插件可以自主升级,不用随着宿主APP发版。

热修复

在使用插件化技术的同时,也可以使用插件中的新的类来替换宿主同名的类,这样就能修复宿主中原有的类存在的BUG。相比插件化,热修复因为不需要考虑组件和res资源的问题,所以相对简单得许多,要保证插件种新的类的加载要在加载宿主中原有类的之前。

拆分DEX

相信大家都知道打包DEX时65536方法数超标问题,也就是一个DEX只能有65536个方法,因此有了multi-dex的解决方案,把本来只有一个的DEX,拆分成复数以上的DEX,运行时挨个加载进来,这其实也算是一种动态加载,只不过实现过程对开发者是透明的。

除此之外,还有另一种拆分DEX是用于减少冷启动的时间的。冷启动是指应用第一次从用户点击到完成初始化工作的全部过程。随着现在APP的体积不断增长,一些APP的DEX文件十分庞大,APP在启动的时候,单单加载所有的DEX文件就需要非常多的耗时,所以用户点击APP的时候会有一个明显的卡顿过程。因此有一种拆分DEX的方案是“拆分一个启动闪屏用的DEX,里面只存放启动闪屏界面需要用到的类,因此非常小,其他类放到其他DEX里面”,启动的时候因为只需要加载闪屏的DEX,所以非常快,APP进入闪屏后,通过异步任务去完成其他DEX的加载,就能消除卡顿的过程。

第一种拆分DEX是官方支持的,开发者只需要打开multi-dex功能即可;第二种拆分DEX则需要开发者自己设计。

基于ClassLoader的动态加载都有个共同的特点,就是新的类一旦加载进内存了,就无法再次替换了,所以无法在运行时候升级功能,需要重启APP才能生效。

运行在Native

有另一种动态加载方式是工作在Native层的,相比于ClassLoader,在Native层的动态加载不需要重新启动APP就能生效,这类的加载有 加载SO库 和 基于JNI HOOK 的热修复。

加载SO库

加载SO库是最常见的Native动态加载,我们项目经常中使用SO库,编译APP的时候,SO并不会参与编译,会原封不动被拷贝到APK包里的lib目录下,安装APK的时候,系统会扫描lib文件夹下支持当前设备CPU类型(比如arm或x86)的SO库(APK包会带有多种CPU类型对应的SO库,安装的时候只需要对应类型的)并拷贝到系统安装目录,APP在运行时可以调用 System#loadLibrary 方法动态加载对应的SO库,此外还可以调用 System#load 加载指定路径上的SO库。

现在的APK里面往往带有非常多的SO库,而APP运行时只需要用到对应CPU类型的SO库,因此把SO库从APK包里剥离出来也是APK瘦身的有效手段。

JNI HOOK

基于JNI HOOK的热修复技术的代表框架有阿里巴巴的 AndFix。Android中,修复BUG的方式就是更新类的方法,和ClassLoader通过加载新的类来更换方法的实现的想法一样,AndFix 也是通过更换方法的做法来实现热修复,不过做法比较取巧。Android中执行Native方法的时候,会去SO库中查找对应的C/C++方法,而 AndFix 先把普通Java方法用Native方法代替,再通过更换不同SO库还更换Native方法的实现。


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/292396.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

c# 爬虫 -ChromeDriver+HtmlAgilityPack爬取比赛实时比分

背景最近NBA总决赛吸引了不少球迷,但是因为时差的关系,人家在比赛,我们在上班,有时候上班又不好意思光明正大的看比赛,那有什么办法 可以光明正大的看又不被发现呢。有,自己动手丰衣足食,Chrome…

Codevs2157 配对

题目描述 Description给出2个序列A{a[1],a[2],…,a[n]},B{b[1],b[2],…,b[n]},从A、B中各选出n个元素进行一一配对(可以不按照原来在序列中的顺序)&#xff0…

UITableView的优化原理

2019独角兽企业重金招聘Python工程师标准>>> 当我们下啦一个 UITableView时,如果没有做优化,只是简单的实现功能代码如下,这样当我们有上百条tableviewcell的时候,我们滑动的非常快时会非常费内存,当然苹果…

深入浅出Mybatis系列(一)---Mybatis入门[转]

最近两年 springmvc mybatis 的在这种搭配还是蛮火的,楼主我呢,也从来没真正去接触过mybatis, 趁近日得闲, 就去学习一下mybatis吧。 本次拟根据自己的学习进度,做一次关于mybatis 的一系列教程, 记录自己的学习历程&…

字符串之括号的有效性

题目: 给定一个字符串str,判断是不是整体有效的括号字符串 举例: str = "()" return true; stre = "()()" return true; str = "())" return false; str = "()a()" return false; 代码: package com.chenyu.string.cn;public class…

python为text添加滚动条_在Tkinter中向一组小部件添加滚动条

概述您只能将滚动条与一些小部件关联起来,根小部件和Frame不是那组小部件的一部分。最常见的解决方案是创建一个画布小部件,并将滚动条与该小部件关联起来。然后,将包含标签小部件的框架嵌入到画布中。确定框架的宽度/高度,并将其…

C# 图像模板匹配并标注

01—需求这个是粉丝在我的技术群提的一个需求1、 模板匹配 :功能:(1)在一张大图像中,选取一小块区域作为模板(2)可在大图像中匹配到模板图像和位置。模板匹配是图像处理中最基本、最常用的匹配方…

深入浅出Mybatis系列(八)---mapper映射文件配置之select、resultMap[转]

上篇《深入浅出Mybatis系列(七)---mapper映射文件配置之insert、update、delete》介绍了insert、update、delete的用法,本篇将介绍select、resultMap的用法。select无疑是我们最常用,也是最复杂的,mybatis通过resultMa…

李洪强经典面试题146-网络

李洪强经典面试题146-网络 网络 http请求方式? 通常,HTTP的请求方式有3种,分别是:POST、GET、HEAD。POST和GET方法是用于数据发送的。 POST:它将要发送的数据单独放在一个流中进行发送,而不是附加在URL地址…

北大保送、硕博连读!《西游记》红孩儿扮演者现成中科院博士!

全世界只有3.14 % 的人关注了爆炸吧知识本文转自:募格学术86版《西游记》可以说是很多人的记忆,男女老幼几乎都看过这个版本,虽然已经过去三十多年,但如今依旧是经典无法超越之作。看过86版《西游记》的小伙伴应该都还记得里面牛魔…

Android插件化开发之运行未安装apk的activity

1、介绍 我们知道PathClassLoader是一个应用的默认加载器(而且他只能加载data/app/xxx.apk的文件),但是我们加载插件一般使用DexClassLoader加载器,所以这里就有问题了,其实如果对于开始的时候,每个人都会认为很简单,…

理解UI线程——SWT, Android, 和Swing的UI机理

2019独角兽企业重金招聘Python工程师标准>>> 在做GUI的时候, 无论是SWT, AWT, Swing 还是Android, 都需要面对UI线程的问题, UI线程往往会被单独的提出来单独对待, 试着问自己, 当GUI启动的时候, 后台会运行几个线程? 比如 1. SWT 从Main函数启动 2. Swing 从Ma…

python自动填写小程序表单_新年好!教大家用Python写一个自动回复拜年信息的小程序!...

原标题:新年好!教大家用Python写一个自动回复拜年信息的小程序!过年期间,想必大家都收到很多拜年信息吧!有没有也被拜年短信(大部分是群发)搞得很焦虑?不回复似乎显得很没有礼貌,一一回复又累心…

C#多线程开发-并发集合中的ConcurrentQueue

前言大家好,我是阿辉。上一篇博文简单介绍了C#中支持并发的数据字典,简单举例说明比较了常规集合与ConcurrentDictionary的读写速度。下来简单介绍其中一个线程安全队列ConcurrentQueue;ConcurrentQueue队列我们不陌生,在数据结构这门课中就有…

HDU 5141

这个题 LIS 并查集的思想 链式前向星 要求找s(i,j)使i j 能有最长的LIS 。。。 做法是枚举每一个j 即终点 算 起点 的可能 无力吐槽了 bc 的时候写错了一个地方 导致TLE 后来幡然醒悟了 改了就a了 不想说什么了 直接上代码 #include <cstdio> #include <…

MySQL存储过程相互调用

什么都不说了上代码&#xff1a; 方式一&#xff1a; 第一个存储过程&#xff1a;test1,参数如下&#xff1a;IN user_name VARCHAR(50),OUT uid bigint(20) BEGIN#Routine body goes here...DECLARE u_id BIGINT(20) DEFAULT 11;SELECT user_id INTO uid FROM tbl_useralias …

一个人动情之后的表现......

1 卖家能有什么坏心思呢&#xff08;via.城与橙与澄&#xff0c;侵删&#xff09;▼2 严重怀疑传了答案▼3 别说我还真没留意到&#xff08;素材来源网络&#xff0c;侵删&#xff09;▼4 领导说“辛苦了”&#xff0c;你要怎么回答▼5 哦吼&#xff08;素材来源网络&#…

Android之推荐看的Android源码

推荐阅读的源码 AOSP项目这么庞大,就算是Framework部分也有够看上一阵子的,所以推荐从常用的看起,由浅及深,同时向横向和纵向深入阅读。 开始 Handler-Message-Looper Handler被称为“异步提交器”,是Android开发入门教程必定谈及的东西,这也是Activity等组件的工作机…

线性代数第五版吉尔伯特课后答_线性代数同济第五版第六章课后习题答案!

搜集 | 整理 | 测试 | 小愉免责声明&#xff1a;以下资源或软件均来自互联网&#xff0c;仅供学习和交流使用&#xff0c;如有侵权请联系删除&#xff0c;请勿用于商业和非法途径等&#xff0c;如有法律纠纷与本人无关&#xff01;本文未经允许&#xff0c;不得转载&#xff0…