Android分包MultiDex策略详解


Posted in Python onOctober 30, 2017

1.分包背景

这里首先介绍下MultiDex的产生背景。

当Android系统安装一个应用的时候,有一步是对Dex进行优化,这个过程有一个专门的工具来处理,叫DexOpt。DexOpt的执行过程是在第一次加载Dex文件的时候执行的。这个过程会生成一个ODEX文件,即Optimised Dex。执行ODex的效率会比直接执行Dex文件的效率要高很多。

但是在早期的Android系统中,DexOpt有一个问题,DexOpt会把每一个类的方法id检索起来,存在一个链表结构里面。但是这个链表的长度是用一个short类型来保存的,导致了方法id的数目不能够超过65536个。当一个项目足够大的时候,显然这个方法数的上限是不够的。尽管在新版本的Android系统中,DexOpt修复了这个问题,但是我们仍然需要对低版本的Android系统做兼容。

为了解决方法数超限的问题,需要将该dex文件拆成两个或多个,为此谷歌官方推出了multidex兼容包,配合AndroidStudio实现了一个APK包含多个dex的功能。

我们在Android开发中,会不断的在App代码里面增加新功能,引入新的类库,如果不加控制的话,那么会碰到编辑器IDE爆出一下错误:

Error:Execution failed for task ':ttt:transformClassesWithDexForDebug'.
com.android.build.api.transform.TransformException: com.android.ide.common.process.ProcessException: java.util.concurrent.ExecutionException: com.android.dex.DexIndexOverflowException: method ID not in [0, 0xffff]: 65536

这个错误是Android应用的对方法总数有限制造成的。Android平台的Java虚拟机Dalvik在执行DEX格式的Java应用程序时,使用原生类型short来索引DEX文件中的方法。这意味着单个DEX文件可被引用的方法总数被限制为65536。通常APK包含一个classes.dex文件,因此Android应用的方法总数不能超过这个数量,这包括Android框架、类库和你自己开发的代码。

这个问题可以通过将一个DEX文件分拆成多个DEX文件解决。

2. 分包策略实现

Gradle 配置:

defaultConfig {  
    applicationId "XXX"
    minSdkVersion 14
    targetSdkVersion 23
    multiDexEnabled true
}
.......
dependencies {
  compile 'com.android.support:multidex:1.0.0'
}

在应用的Application 类重写方法:

@Override
protected void attachBaseContext(Context base) {
  super.attachBaseContext(base);
  MultiDex.install(this);
}

3.分包效果说明

经过以上的配置,你的应用已经可以实现多个DEX文件了。当应用构建时,构建工具会分析哪些类必须放在第一个DEX文件,哪些类可以放在附加的DEX文件中。当它创建了第一个DEX文件后,如果有必要会继续创建附加的DEX文件,如classes2.dex, classes3.dex。Multidex的支持类库将被包含在应用的第一个DEX文件中,帮助实现对其它DEX文件的访问。

虽然Google解决了应用总方法数限制的问题,但并不意味着开发者可以任意扩大项目规模。Multidex仍有一些限制:

DEX文件安装到设备的过程非常复杂,如果第二个DEX文件太大,可能导致应用无响应。此时应该使用ProGuard减小DEX文件的大小。

由于Dalvik linearAlloc的Bug,应用可能无法在Android 4.0之前的版本启动,如果你的应用要支持这些版本就要多执行测试。
同样因为Dalvik linearAlloc的限制,如果请求大量内存可能导致崩溃。Dalvik linearAlloc是一个固定大小的缓冲区。在应用的安装过程中,系统会运行一个名为dexopt的程序为该应用在当前机型中运行做准备。dexopt使用LinearAlloc来存储应用的方法信息。Android 2.2和2.3的缓冲区只有5MB,Android 4.x提高到了8MB或16MB。当方法数量过多导致超出缓冲区大小时,会造成dexopt崩溃。

-Multidex构建工具还不支持指定哪些类必须包含在首个DEX文件中,因此可能会导致某些类库(例如某个类库需要从原生代码访问Java代码)无法使用。

4.对开发者的建议

开发者应该避免使用Google Guava这样的类库,它包含了13000多个方法。

尽量使用专为移动应用设计的Lite/Android版本类库,或者使用小类库替换大类库,例如用Google-gson替换Jackson JSON。而对于Google Protocol Buffers这样的数据交换格式,其标准实现会自动生成大量的方法。采用Square Wire的实现则可以很好地解决此问题。

在出现应用分包后低版本手机无法使用,高版本正常使用的问题时,可以考虑检查一下分包的配置是否正确。

总结

以上就是本文关于Android分包MultiDex策略详解的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站其他相关内容,如有不足之处,欢迎留言指出。

Python 相关文章推荐
python调用cmd命令行制作刷博器
Jan 13 Python
在Python的Flask框架中验证注册用户的Email的方法
Sep 02 Python
python中的随机函数小结
Jan 27 Python
Python编程argparse入门浅析
Feb 07 Python
对python3 一组数值的归一化处理方法详解
Jul 11 Python
Python数据预处理之数据规范化(归一化)示例
Jan 08 Python
Python爬虫库BeautifulSoup的介绍与简单使用实例
Jan 25 Python
django实现HttpResponse返回json数据为中文
Mar 27 Python
Keras搭建自编码器操作
Jul 03 Python
Python 捕获代码中所有异常的方法
Aug 03 Python
Python 实现PS滤镜中的径向模糊特效
Dec 03 Python
使用Pytorch实现two-head(多输出)模型的操作
May 28 Python
Python 判断是否为质数或素数的实例
Oct 30 #Python
基于Python __dict__与dir()的区别详解
Oct 30 #Python
浅谈使用Python变量时要避免的3个错误
Oct 30 #Python
Python中进程和线程的区别详解
Oct 29 #Python
python logging日志模块的详解
Oct 29 #Python
解决出现Incorrect integer value: '' for column 'id' at row 1的问题
Oct 29 #Python
Python批量更改文件名的实现方法
Oct 29 #Python
You might like
php报表之jpgraph柱状图实例代码
2011/08/22 PHP
ExtJs默认的字体大小改变的几种方法(自己整理)
2013/04/18 Javascript
jquery eval解析JSON中的注意点介绍
2013/08/23 Javascript
JQuery中对Select的option项的添加、删除、取值
2013/08/25 Javascript
jQuery图片轮播的具体实现
2013/09/11 Javascript
JS修改iframe页面背景颜色的方法
2015/04/01 Javascript
JavaScript简单获取页面图片原始尺寸的方法
2016/06/21 Javascript
JS简单判断字符在另一个字符串中出现次数的2种常用方法
2017/04/20 Javascript
Angular5升级RxJS到5.5.3报错:EmptyError: no elements in sequence的解决方法
2018/04/09 Javascript
如何在vue里添加好看的lottie动画
2018/08/02 Javascript
微信公众平台获取access_token的方法步骤
2019/03/29 Javascript
vue按需加载实例详解
2019/09/06 Javascript
微信小程序在text文本实现多种字体样式
2019/11/08 Javascript
vue router返回到指定的路由的场景分析
2020/11/10 Javascript
探究Python中isalnum()方法的使用
2015/05/18 Python
Python文件去除注释的方法
2015/05/25 Python
以视频爬取实例讲解Python爬虫神器Beautiful Soup用法
2016/01/20 Python
Python数据结构之翻转链表
2017/02/25 Python
python3实现公众号每日定时发送日报和图片
2018/02/24 Python
Python 支付整合开发包的实现
2019/01/23 Python
Python基础学习之类与实例基本用法与注意事项详解
2019/06/17 Python
python 模拟贷款卡号生成规则过程解析
2019/08/30 Python
浅谈Python类中的self到底是干啥的
2019/11/11 Python
如何通过python实现全排列
2020/02/11 Python
如何查看Django ORM执行的SQL语句的实现
2020/04/20 Python
完美解决pycharm 不显示代码提示问题
2020/06/02 Python
如何将Pycharm中调整字体大小的方式设置为"ctrl+鼠标滚轮上下滑"
2020/11/17 Python
详解css3使用transform出现字体模糊的解决办法
2020/10/16 HTML / CSS
使用CSS实现弹性视频html5案例实践
2012/12/26 HTML / CSS
Beauty Expert美国/加拿大:购买奢侈美容产品
2018/12/05 全球购物
Everything But Water官网:美国泳装品牌
2019/03/17 全球购物
工程专业应届生求职信
2014/02/19 职场文书
幼儿园父亲节活动方案
2014/03/11 职场文书
《中国梦我的梦》小学生演讲稿
2014/08/20 职场文书
2014年学校党建工作汇报材料
2014/11/02 职场文书
治理商业贿赂工作总结
2015/08/10 职场文书