(转)美团Android DEX自动拆包及动态加载简介
来源:互联网 发布:osek网络管理 编辑:程序博客网 时间:2024/06/03 23:00
原文链接:http://tech.meituan.com/mt-android-auto-split-dex.html
概述
作为一个android开发者,在开发应用时,随着业务规模发展到一定程度,不断地加入新功能、添加新的类库,代码在急剧的膨胀,相应的apk包的大小也急剧增加, 那么终有一天,你会不幸遇到这个错误:
生成的apk在android 2.3或之前的机器上无法安装,提示INSTALL_FAILED_DEXOPT
方法数量过多,编译时出错,提示:
Conversion to Dalvik format failed:Unable to execute dex: method ID not in [0, 0xffff]: 65536
而问题产生的具体原因如下:
无法安装(Android 2.3 INSTALL_FAILED_DEXOPT)问题,是由dexopt的LinearAlloc限制引起的,在Android版本不同分别经历了4M/5M/8M/16M限制,目前主流4.2.x系统上可能都已到16M, 在Gingerbread或者以下系统LinearAllocHdr分配空间只有5M大小的, 高于Gingerbread的系统提升到了8M。Dalvik linearAlloc是一个固定大小的缓冲区。在应用的安装过程中,系统会运行一个名为dexopt的程序为该应用在当前机型中运行做准备。dexopt使用LinearAlloc来存储应用的方法信息。Android 2.2和2.3的缓冲区只有5MB,Android 4.x提高到了8MB或16MB。当方法数量过多导致超出缓冲区大小时,会造成dexopt崩溃。
超过最大方法数限制的问题,是由于DEX文件格式限制,一个DEX文件中method个数采用使用原生类型short来索引文件中的方法,也就是4个字节共计最多表达65536个method,field/class的个数也均有此限制。对于DEX文件,则是将工程所需全部class文件合并且压缩到一个DEX文件期间,也就是Android打包的DEX过程中, 单个DEX文件可被引用的方法总数(自己开发的代码以及所引用的Android框架、类库的代码)被限制为65536;
插件化? MultiDex?
解决这个问题,一般有下面几种方案,一种方案是加大Proguard的力度来减小DEX的大小和方法数,但这是治标不治本的方案,随着业务代码的添加,方法数终究会到达这个限制,一种比较流行的方案是插件化方案,另外一种是采用google提供的MultiDex方案,以及google在推出MultiDex之前Android Developers博客介绍的通过自定义类加载过程, 再就是Facebook推出的为Android应用开发的Dalvik补丁, 但facebook博客里写的不是很详细;我们在插件化方案上也做了探索和尝试,发现部署插件化方案,首先需要梳理和修改各个业务线的代码,使之解耦,改动的面和量比较巨大,通过一定的探讨和分析,我们认为对我们目前来说采用MultiDex方案更靠谱一些,这样我们可以快速和简洁的对代码进行拆分,同时代码改动也在可以接受的范围内; 这样我们采用了google提供的MultiDex方式进行了开发。
插件化方案在业内有不同的实现原理,这里不再一一列举,这里只列举下Google为构建超过65K方法数的应用提供官方支持的方案:MultiDex。
首先使用Android SDK Manager升级到最新的Android SDK Build Tools和Android Support Library。然后进行以下两步操作:
1.修改Gradle配置文件,启用MultiDex并包含MultiDex支持:
android {
compileSdkVersion 21 buildToolsVersion “21.1.0”
defaultConfig { ... minSdkVersion 14 targetSdkVersion 21 ... // Enabling MultiDex support. MultiDexEnabled true } ...}dependencies { compile 'com.android.support:MultiDex:1.0.0'
}
2.让应用支持多DEX文件。在官方文档中描述了三种可选方法:
在AndroidManifest.xml的application中声明android.support.MultiDex.MultiDexApplication;
如果你已经有自己的Application类,让其继承MultiDexApplication;
如果你的Application类已经继承自其它类,你不想/能修改它,那么可以重写attachBaseContext()方法:
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
MultiDex.install(this);
}
并在Manifest中添加以下声明:
- (转)美团Android DEX自动拆包及动态加载简介
- 美团Android DEX自动拆包及动态加载简介
- 美团Android DEX自动拆包及动态加载简介
- 美团Android DEX自动拆包及动态加载简介
- 美团Android DEX自动拆包及动态加载简介
- 美团Android DEX自动拆包及动态加载简介
- 美团Android DEX自动拆包及动态加载简介
- 美团Android DEX自动拆包及动态加载简介
- 美团Android DEX自动拆包及动态加载简介
- 美团Android DEX自动拆包及动态加载简介
- 美团Android DEX自动拆包及动态加载简介
- 美团Android DEX自动拆包及动态加载简介
- 美团Android DEX自动拆包及动态加载简介
- 美团Android DEX自动拆包及动态加载简介
- 美团Android DEX自动拆包及动态加载简介
- 美团Android DEX自动拆包及动态加载简介
- Android DEX自动拆包及动态加载简介
- Android DEX自动拆包及动态加载简介
- 基于Dragon Board410c 的智能机器人预研-语音识别及定位
- c# textbox显示文本获取行数
- Maven 仓库手动安装jar
- PHP工程师技能水平区分
- 程序猿必须知道的编程语言发展史——信息图
- (转)美团Android DEX自动拆包及动态加载简介
- 服务间的通讯
- 挑战面试编程:查找数组中第k大的数
- 开始运行命令集锦
- android热更新
- 声明一个block宏
- onActivityResult 不调用的问题
- 安卓pulltorefresh使用小结
- iOS_SpriteKit_03_精灵平移拖动