需要分Dex的理由想必大家都知道了.正是在ART以前的Android系统中,Dex文件对于方法索引是用一个short类型的数据来存放的.而short的最大值是65535,因此当项目足够大包含方法数目足够多超过了65535(包括引用的外部Lib里面的所有方法),当运行App,就会得到如下的错误提示.

Unable to execute dex: method ID not in [, 0xffff]:
Conversion to Dalvik format failed: Unable to execute dex: method ID not in [, 0xffff]:

这个致命严重的Bug出现后,Android官方就写了一篇著名的Blog(这篇文章我读了五六遍,甚至连作者的Google+的照片我都看了两三次,我还是没有完全搞明白怎么Walkaround这个严重的问题).

再后来,慢慢发展,有很多能人异士发挥自己的创造力,写了开源的Lib放在GitHub上分享给其他Android开发者们使用.HelloMultiDex, Secondary-Dex-Gradle等等.

但是解铃还须系铃人,这种系统性的严重致命Bug,当然还是Android官方给出解决方案最让人放心.终于,我们还是等到了你,MultiDex Offical Solution.

我推荐官方文档这篇GitHub的文章一起看会有更好的了解,少走弯路.

下面说一说使用的步骤:

1. 修改Gradle,导入'com.android.support:multidex:1.0.0',打开multiDexEnabled;

android {
compileSdkVersion
buildToolsVersion "21.1.0" defaultConfig {
...
minSdkVersion
targetSdkVersion
... // Enabling multidex support.
multiDexEnabled true
}
...
} dependencies {
compile 'com.android.support:multidex:1.0.0'
}

2.修改Application.两种方法:

1) 直接把Application替换成MultiDexApplication

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.android.multidex.myapplication">
<application
...
android:name="android.support.multidex.MultiDexApplication">
...
</application>
</manifest>

2) 在原来的Application中修改调用MultiDex.install(this);

public class HelloMultiDexApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
} @Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
MultiDex.install(this);
}
}

到这里其实MultiDex的配置已经完成了.

但是,实际上下面介绍的3个问题也非常值得我们关注.

1. 一些在二级Dex加载之前,可能会被调用到的类(比如静态变量的类),需要放在主Dex中.否则会ClassNotFoundError.

通过修改Gradle,可以显式的把一些类放在Main Dex中.

afterEvaluate {
tasks.matching {
it.name.startsWith('dex')
}.each { dx ->
if (dx.additionalParameters == null) {
dx.additionalParameters = []
}
dx.additionalParameters += '--multi-dex'
dx.additionalParameters += "--main-dex-list=$projectDir/<filename>".toString()
}
}

上面是修改后的Gradle,其中<filename>是一个文本文件的文件名,存放在和这个Gradle脚本同一级的文件目录下.

而这个文本文件的内容如下.实际就是把需要放在Main Dex的类罗列出来.

android/support/multidex/BuildConfig/class
android/support/multidex/MultiDex$V14/class
android/support/multidex/MultiDex$V19/class
android/support/multidex/MultiDex$V4/class
android/support/multidex/MultiDex/class
android/support/multidex/MultiDexApplication/class
android/support/multidex/MultiDexExtractor$/class
android/support/multidex/MultiDexExtractor/class
android/support/multidex/ZipUtil$CentralDirectory/class
android/support/multidex/ZipUtil/class

2. 如果用使用其他Lib,要保证这些Lib没有被preDex,否则可能会抛出下面的异常

UNEXPECTED TOP-LEVEL EXCEPTION:
com.android.dex.DexException: Library dex files are not supported in multi-dex mode
at com.android.dx.command.dexer.Main.runMultiDex(Main.java:337)
at com.android.dx.command.dexer.Main.run(Main.java:243)
at com.android.dx.command.dexer.Main.main(Main.java:214)
at com.android.dx.command.Main.main(Main.java:106)

遇到这个异常,需要在Gradle中修改,让它不要对Lib做preDexing

android {
// ...
dexOptions {
preDexLibraries = false
}
}

3. 如果每次都打开MultiDex编译版本的话,会比平常用更多的时间(这个也容易理解,毕竟做了不少事情)

Android的官方文档也给了我们一个小小的建议,利用Gradle建立两个Flavor.一个minSdkVersion设置成21,这是用了ART支持的Dex格式,避免了MultiDex的开销.而另外一个Flavor就是原本支持的最小sdkVersion.平时开发时候调试程序,就用前者的Flavor,发布版本打包就用后者的Flavor.

android {
productFlavors {
// Define separate dev and prod product flavors.
dev {
// dev utilizes minSDKVersion = 21 to allow the Android gradle plugin
// to pre-dex each module and produce an APK that can be tested on
// Android Lollipop without time consuming dex merging processes.
minSdkVersion 21
}
prod {
// The actual minSdkVersion for the application.
minSdkVersion 14
}
}
...
buildTypes {
release {
runProguard true
proguardFiles getDefaultProguardFile('proguard-android.txt'),
'proguard-rules.pro'
}
}
}
dependencies {
compile 'com.android.support:multidex:1.0.0'
}

有了Android官方的支持后,MultiDex比最原始的解决方案简单多了.妈妈再也不用担心我们要分Dex啦!

最新文章

  1. CALayer的transform属性
  2. Borland C++建立工程菜鸟教程
  3. wep.py输出hello world
  4. Latest node.js &amp; npm installation on Ubuntu 12.04
  5. linux下删除文件名乱码文件
  6. Android SDK代理服务器解决国内不能更新下载问题(转)
  7. HDU 5815 - Golden Week
  8. struts的由来
  9. 小程序开发教程:wx.setTopBarText(OBJECT)
  10. 201521123035《Java程序设计》第十三周学习总结
  11. 将 Net 项目升级 Core项目经验:(二)修复迁移后Net Standard项目中的错误
  12. EventQueue.invokeLater(new Runnable())
  13. 加载hive-jdbc driver时报错:java.lang.NoClassDefFoundError: org/apache/hadoop/conf/Configuration
  14. [Swift]LeetCode756. 金字塔转换矩阵 | Pyramid Transition Matrix
  15. 注解式controller开发,action找不到controller???
  16. iOS 在 程序内调用手机上安装的地图软件进行导航
  17. Linux的远程管理
  18. ruby计算完成率
  19. JQuery Tree插件
  20. MyBatis最初的程序解读---API

热门文章

  1. 20155338 2016-2017-2 《JAVA程序设计》课程总结
  2. 微信小程序解决地图上的层级关系
  3. Odoo中创建模块语句
  4. 【转载】ID3DXSPRITE接口简单使用
  5. mybatis SQL映射配置文件
  6. AWS探索及创建一个aws EC2实例
  7. Python教程 深入条件控制
  8. 【jpeg_Class 类】使用说明
  9. Spring Task中的定时任务无法注入service的解决办法
  10. C++数字三角形问题与dp算法