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基础教程之面向对象的一些概念
Aug 29 Python
python实现比较两段文本不同之处的方法
May 30 Python
python密码错误三次锁定(实例讲解)
Nov 14 Python
Python数据分析之双色球基于线性回归算法预测下期中奖结果示例
Feb 08 Python
使用python3+xlrd解析Excel的实例
May 04 Python
使用python3调用wxpy模块监控linux日志并定时发送消息给群组或好友
Jun 05 Python
Django命名URL和反向解析URL实现解析
Aug 09 Python
PyQt+socket实现远程操作服务器的方法示例
Aug 22 Python
python库matplotlib绘制坐标图
Oct 18 Python
python实现大量图片重命名
Mar 23 Python
Python tkinter布局与按钮间距设置方式
Mar 04 Python
Python Dataframe常见索引方式详解
May 27 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
乐信RP2100的电路分析和打磨
2021/03/02 无线电
模仿OSO的论坛(五)
2006/10/09 PHP
收集的PHP中与数组相关的函数
2007/03/22 PHP
一步一步学习PHP(8) php 数组
2010/03/05 PHP
Zend Framework分页类用法详解
2016/03/22 PHP
PHP使用file_get_contents发送http请求功能简单示例
2018/04/29 PHP
thinkPHP框架实现类似java过滤器的简单方法示例
2018/09/05 PHP
ExtJs事件机制基本代码模型和流程解析
2010/10/24 Javascript
Jquery 获取指定标签的对象及属性的设置与移除
2014/05/29 Javascript
Node.js 的异步 IO 性能探讨
2014/10/08 Javascript
jquery实现带缩略图的可定制高度画廊效果(5种)
2015/08/28 Javascript
详解Matlab中 sort 函数用法
2016/03/20 Javascript
Node.js文件操作方法汇总
2016/03/22 Javascript
jQuery 翻页组件yunm.pager.js实现div局部刷新的思路
2016/08/11 Javascript
JavaScript中this的四个绑定规则总结
2016/09/26 Javascript
为Jquery EasyUI 组件加上清除功能的方法(详解)
2017/04/13 jQuery
简单实现vue验证码60秒倒计时功能
2017/10/11 Javascript
浅谈Angular 中何时取消订阅
2017/11/22 Javascript
python获取元素在数组中索引号的方法
2015/07/15 Python
详解Django框架中用context来解析模板的方法
2015/07/20 Python
基于Python的文件类型和字符串详解
2017/12/21 Python
火车票抢票python代码公开揭秘!
2018/03/08 Python
深入浅析python3中的unicode和bytes问题
2019/07/03 Python
Python模块汇总(常用第三方库)
2019/10/07 Python
python入门:argparse浅析 nargs='+'作用
2020/07/12 Python
Pycharm及python安装详细教程(图解)
2020/07/31 Python
HTML5时代CSS设置漂亮字体取代图片
2014/09/04 HTML / CSS
澳大利亚床上用品、浴巾和家居用品购物网站:Bambury
2020/04/16 全球购物
行政助理的职责
2013/11/14 职场文书
十八届三中全会感言
2014/03/10 职场文书
防灾减灾标语
2014/10/07 职场文书
工程承包协议书
2014/10/20 职场文书
2014幼儿教师个人工作总结
2014/12/03 职场文书
vue项目多环境配置(.env)的实现
2021/07/21 Vue.js
详解JavaScript中Arguments对象用途
2021/08/30 Javascript
如何利用python实现列表嵌套字典取值
2022/06/10 Python