64K方法数限制解决办法

来源:互联网 发布:神彩彩票源码 编辑:程序博客网 时间:2024/06/18 08:49

随着业务逻辑越来越多,业务模块也越来越大,不可避免会遇到64K方法数的限制。最直观的表现就是编译报错:

较早版本的编译系统中,错误内容如下:

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

较新版本的编译系统中,错误内容如下:

trouble writing output:Too many field references: 131000; max is 65536.You may try using --multi-dex option.

64K限制的原因

Android APK文件本质上是一个压缩文件,它包含的classes.dex文件是可执行的Dalvik字节码文件,这个.dex文件中存放的就是编译后的Java代码。Dalvik可执行文件规范限制了单个.dex文件最多引用的方法数是65536个。其中包含联网Android Framework、APP引用的第三方函数库以及APP自身的方法。

使用MultiDex解决64K限制的问题

Android 5.0之前的版本

Android 5.0之前系统使用的Dalvik虚拟机默认为每个APK只生成一个classes.dex文件,为了规避单个.dex文件超过64K的问题,我们拆分成多个classes.dex文件。启动应用时先加载的classex.dex为主dex文件,其他的为从dex文件。Google推出一个名为MultiDex Support Library的函数库来避免这个问题。

Android 5.0及之后的版本

Android 5.0 之后使用ART来代替Dalvik虚拟机,ART天然支持从APK文件中加载多个.dex文件。在应用安装期间,它会执行一个预编译操作,并将多个单一的.dex文件编译成一个单一的.oat文件,应用运行时区加载这个.oat文件,而不是再去一个一个加载.dex文件。

配置MultiDex

Android Gradle 插件在 Android SDK Build Tools 21.1 及更高版本的编译工具上支持multidex作为编译配置的一部分,所以确保我们的Android SDK Build Tools tools已经更新至21.1或更高版本,然后再来配置应用的multidex部分。

第一步,修改app/build.grale文件,使项目能够使用multidex:

android {    compileSdkVersion 21    buildToolsVersion "21.1.0"  // 这里必须要21.1.0之后    defaultConfig {        minSdkVersion 14        targetSdkVersion 21        ...        // Enabling multidex support.        multiDexEnabled true    }    ...}dependencies {  compile 'com.android.support:multidex:1.0.1'}

第二步,修改AndroidManifest.xml文件,引用MultiDexApplication类:

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

如果用户继承变重写了Application,可以将继承的Application换成MultiDexApplication。

public class MyApplication extends MultiDexApplication {    @Override    public void onCreate() {        super.onCreate();    }}

或者重写attachBaseContext() 方法

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

特别注意,如果没有实现这部分代码,运行时会出现NoClassDefFoundError的错误,尤其是在依赖三方函数库时。

在开发阶段优化MultiDex的构建

multidex会加长构建应用的时间,这个必要的过程可能会拖慢你的开发进度。原因在于构建系统需要经过复杂的计算决定哪些类要包含在主.dex文件中,哪些类可以包含在从dex文件中。 为加速构建过程,我们可以在Gradle中配置productFlavors来创建两个flavor:一个是开发阶段使用的,一个是生产阶段使用的。开发阶段将minSdkVersion改为21使用ART运行时机制,这样能加快构建速度。release时改为合适的minSdkVersion,这样仅在release时费时较长。

android {    compileSdkVersion 21    buildToolsVersion "21.1.0"  // 这里必须要21.1.0之后    productFlavors{    // 配置不同的falvor        dev {            minSdkVersion 21     // 开发环境的minSdkVersion         }        prod {            minSdkVersion 14    // 生产环境的minSdkVersion         }    }    ...}dependencies {  compile 'com.android.support:multidex:1.0.1'}
  1. 这里每个module对应的.dex文件不会被合并,因此避免了决定哪些类要放在主dex文件中的耗时计算。
  2. 只能在Android 5.0 设备上进行测试
原创粉丝点击