热修复框架?我们都能做出来!

一、背景

① 为什么会出现热修复技术?

大家都是开发,所以应该都知道有一个东西我们永远也避免不了。不错,Bug!我们在开发阶段碰到bug那还好,直接解决就是了,大不了让测试多测一轮。可是,如果我们发出去的版本出现线上Bug,那可怎么办?大多数小的公司可能会选择,重新发新的版本去覆盖安装。这种方式成本较高,而且用户一般都比较讨厌经常需要更新版本的APP。对于小公司来说,出现线上问题影响范围还是比较小的,毕竟用户量较少。可是对于一些巨头公司,有些问题不能及时修复那是致命的。所以呢,有这么一些技术储备和能力比较高的公司为我们开了先河。
② 致敬先辈!

对于像手机QQ空间、支付宝、360这样的巨头公司当然无法忍受出现线上Bug要等发版解决。所以他们搞出了热修复的技术方案。Android的热修复技术大多都源于此。
③ 原理简述

说了那么多,那到底热修复是怎样的一个技术呢?
在说热修复之前,我们得先知道我们手机中运行的APP实际是我们写的Java代码编译成class文件,然后打包成dex文件运行在手机中的。也就是说,我们手机里面实际运行的是dex文件。所以,如果我们的APP出现线上问题,90%的可能性是我们写的代码导致的Bug,也就是运行在手机里面的dex文件出现了Bug。所以热修复的思想就是静默的下载服务端的新的dex文件替换出现问题的dex文件。
二、热修复的实现原理

替换dex文件说起来比较简单,但是真实现起来,还是需要我们考虑更多的细节。下面我们围绕这个替换dex文件详细的分析去实现的步骤:
① Dex分包

我们知道在最开始的时候(ART还没有推出),安卓是使用Dalvik虚拟机来运行我们的应用程序的,安卓项目在打包APK的时候,会将所有编译生成的class文件打包成dex文件。并且Dalvik虚拟机在我们安装应用的时候通过DexOpt工具对dex文件进行优化,DexOpt有个缺点,就是在执行的时候会将dex中的类中的所有方法ID检索出来存在一个链表中,而链表的长度定义的类型为short类型,这就导致dex文件中的方法总数不能超过short的范围,也就是不能超过65536个。显然当我们的项目比较大的时候,这个方法数是不够的。所以后面Android就推出了ART这种本身就支持多dex的APK。
讲了这么多,dex分包和我们这里讲的热修复又有什么关系呢?前面我们已经讲了替换dex的思路,如果只有一个dex,不去拆分,显然我们是没办法替换的。要想替换掉发生Bug的dex,我们首先得有能正常运行的dex代码去做替换这件事吧?所以,我们会拆出一个比较稳定的主dex,作为去实现从服务端下载和替换动作的代码。当其他模块出现Bug时,在去更新对应模块的dex文件。那么一般我们如何去拆分dex呢?
在Android5.0之前呢,我们需要引入谷歌提供的multidex.jar支持multidex。所以需要我们首先在项目的build.gradle中加入如下配置①
然后我们借助一个好用的配置分包的第三方库:DexKnife来配置如何分包②。这里就不对DexKnife详细介绍了,读者可以去Dexknife的使用文档上查看详细的使用方法。
② 替换dex文件

替换dex文件的逻辑一般是我们进入主页面以后,请求一个接口查询服务端当前是否有新的dex需要替换,如果有就在后台默默下载后去替换。当然这里面包含一些版本、dex名称等参数去区分。如何去下载文件不在本文的介绍范围,相信读者都做过了。这里主要讲解当我们在服务端下载好了一个需要替换的dex包以后,如何将它替换进去。
在讲替换之前,我们首先得了解一下我们的打包的dex文件是如何被加载到虚拟机运行的。Android里面是使用的BaseDexClassLoader去加载dex中的类,所以接下来我们分析下BaseDexClassLoader的源码。
在这个类中,我们首先看到有一个包装类DexPathList是用来存储需要去加载的dex文件列表,我们继续观察DexPathList的源码,发现:
用dexElements数组存储dex文件的路径,看注释可以知道当时的谷歌的工程师蛮有意思,将Facebook会使用反射调用都写进去了,哈哈,调皮。然后我看看他是如何去给将dex文件目录放到dexElements数组中的呢?
我们可以看到,源码中是将dex文件封装成Element对象存到数组中的。所以,像Facebook或者阿里巴巴、腾讯这样的巨头公司呢看到了其中的本质,也就是Android在加载类的时候,就是在dexElements数组中去遍历dex文件,如果在某一个dex文件中找到了该类就加载。所以,我们的思路是将我们新的修复过Bug的dex文件如果能放到dexElements中的最前面,那么当系统去加载我们出错的类的时候,会优先加载到我们修复过的类了,从而起到修复Bug的作用。
那么,一般是怎么做的呢?首先,我们实例一个BaseDexClassLoader类去加载我们从服务端下载下来的dex文件到内存中,当然这一切需要用到反射去拿到DexPathList类中的dexElements数组,然后将我们的dex文件加载进去成为一个Element对象;然后,我们通过反射拿到我们APP本身的dexElements数组去将我们新的Element放入到最前面。这样就能够让新的dex比有Bug的Dex优先被加载了。
三、小结

本节主要是对使用热修复的来龙去脉,以及我们通过源码的分析找到为什么能够去实现热修复的原因。我们也给大家介绍了使用热修复需要知道的哪些技术点以及业内比较成功的公司。下一节我们将围绕本节的原理以及分析以demo的形式简单实现一个热修复的框架,让读者自己能够轻松实现。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,470评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,393评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,577评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,176评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,189评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,155评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,041评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,903评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,319评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,539评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,703评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,417评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,013评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,664评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,818评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,711评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,601评论 2 353

推荐阅读更多精彩内容