Android热修复三部曲之MultiDex 分包架构
转载请标明出处:
http://blog.youkuaiyun.com/lisdye2/article/details/52094693
本文出自:【Alex_MaHao的博客】
项目中的源码已经共享到github,有需要者请移步【Alex_MaHao的github】
本篇博客基于上一篇博客,Android 热修复三部曲之基本的Ant打包脚本
在上一篇博客中,讲解了使用Ant打包的流程,也编写了相应的脚本代码。但是忘了说明怎么运行了。有两种方式:
- 在Eclipse的build.xml 中,右键run as 即可。
- 通过命令行形式进入到当前工程目录下,输入命令
ant 工程名
。
上一篇漏下的已经补充。下面开始今天博客的主要内容。
该篇博客主要分为三个部分:
- 什么是分包架构
- 分包架构的好处
- 怎么实现分包
什么是分包架构
如果反编译过apk的同学知道,在apk中存在这一个classes.dex
的文件,该文件主要是存放了经过编译后的java代码。那么我们通过一定的手段,在使用dx.bat
打包时,将.class
文件打成多个.dex
文件,便是分包。
分包架构的好处
分包有两个好处:
1.解决65536的错误
我们知道Android 应用的方法数不能超过65536个。也就是一个.dex
文件,起内包含的方法数不能超过65536。这是因为其使用了一个整形来建立相应方法的索引。
2.实现程序的热修复
我们将程序分模块打成了多个.dex
,如果某一个.dex
出现了问题,我们可以对这个出现问题的.dex
重新编译出无bug的.dex
。然后从服务器下载之后,动态的将新的.dex
加入到内存中,覆盖之前的有问题的.dex
,变实现了不发版本的bug
的修复。
实现方式
在上一篇博客中,分析了打包的流程,再来复习一下:
1.初始化配置
2.编译生成 R.java文件
3.编译工程中的 java 代码
4.对.class 文件进行编译生成.dex文件
5.压缩资源文件
6.打出未签名的包
7.对Apk进行签名的
那么我们在第4步的时候做出修改,根据我们的需求打出多个.dex
。在第6步,打出未签名包时,因为其命令中,只能添加一个.dex
,所以需要使用aapt
命令,将其余的.dex
文件放入其中。
开始实现代码:
在第3步完成之后,修改代码如下
<target
name="dex"
depends="compile" >
<echo>
Generate multi-dex...
</echo>
<!-- 分为三个部分 jar 一部分,本地 -->
<exec
executable="${tools.dx}"
failonerror="true" >
<arg value="--dex" />
<arg value="--multi-dex" />
<arg value="--set-max-idx-number=10000" />
<arg value="--minimal-main-dex" />
<arg value="--main-dex-list" />
<arg value="main-dex-rule.txt" />
<arg value="--output=bin" />
<arg value="bin/classes" />
</exec>
<echo>
Generate dex...
</echo>
<exec
executable="${tools.dx}"
failonerror="true" >
<arg value="--dex" />
<arg value="--output=bin/classes3.dex" />
<arg value="${project-dir}/libs" />
<!-- classes文件位置 -->
<arg value="${appcompat-dir}\libs" />
</exec>
</target>
分别执行了两次dx命令,第一次,将src
中的类和R文件,打包成了classes.dex
和classes2.dex
。main-dex-rule.txt
文件中表示那些类会打入到主的.dex
文件中(classes.dex
)。
main-dex-rule.txt文件中就添加了两个.class。
com/alex_mahao/multidex/MainActivity.class
com/alex_mahao/multidex/MyApp.class
第二次将jar包打成一个单独的classes3.dex
文件。
在这里,分成了三个.dex
。
- 程序的主要类,如Application
,MainActivity
等打入到classes.dex
,该程序要保证不会出错,一般就打入几个必要的类。
- 业务逻辑类。这些可能会出错的类,以便于修复。
- jar 包。
之所以将业务逻辑类和jar包类分开,是因为jar包基本上不会变,而如果热修复时加上jar包一起替换,加大了内存的负担。
在执行完第6步操作之后,开始将classes2.dex
和classes3.dex
导入到包中。
复制.dex
文件。
<target
name="copy_dex"
depends="package" >
<echo message="copy dex..." />
<copy todir="${project-dir}" >
<fileset dir="bin" >
<include name="classes*.dex" />
</fileset>
</copy>
</target>
拷贝文件到项目的根目录下面,因为我们的脚本是在根目录下面,这样在运行aapt的时候,可以直接操作dex文件了.
开始导入
<target
name="add-subdex-toapk"
depends="copy_dex" >
<echo message="Add Subdex to Apk ..." />
<foreach
param="dir.name"
target="aapt-add-dex" >
<path>
<fileset
dir="bin"
includes="classes*.dex" />
</path>
</foreach>
</target>
<!-- 使用aapt命令添加dex文件 -->
<target name="aapt-add-dex" >
<echo message=