Android 64K问题详解

1、报错提示

  • 错误一
trouble writing output:
Too many field references: 131000; max is 65536.
You may try using --multi-dex option.
  • 错误二
Conversion to Dalvik format failed:
Unable to execute dex: method ID not in [0, 0xffff]: 65536

从错误信息中可以看出一个关键词 65536,这也就是传说中64k问题。

2、报错原因

Android 5.0 之前(项目中minSdkVersion参数设置为20及以下),安卓系统是Dalvik虚拟机,在编译时Java源文件打包成dex文件,Dalvik虚拟机在执行dex文件的时候,使用short类型索引方法,short类型的范围是(-32,768~32,767),正好是64k,也就是说单个dex文件中方法做多只有65535个,随着项目的不断壮大,引用各种lib、以及项目本身java文件的增加,64k方法已经不能满足需要,因此会报64k问题。

3、 解决方案(只针对5.0 之前,项目中minSdkVersion参数设置为20及以下)

Dalvik虚拟机限制每个app只能生成一个dex文件,要解决这个问题就要用到官方为我们提供的Multidex库,会自动判断方法是否超过65535个,如果超过了会对其做分包处理。最后都会打包进apk里面。分包后dex文件如下:

Android 64K问题详解_第1张图片
图片.png

此时 buildToolsVersion 就要升级到21.1以上,这个是支持Multidex功能的最低版本。

配置Multidex步骤如下:
  • 1、升级buildToolsVersion 到最新(保证21.1以上)
  • 2、启用Multidex(multiDexEnabled 设置为 true)
  • 3、配置Multidex依赖
android {
    compileSdkVersion 27
    // 1、build tools 版本在21.1以上
    buildToolsVersion "27.0.3"

    defaultConfig {
        applicationId "com.example.zpdemo"
        // 5.0 之前
        minSdkVersion 15
        targetSdkVersion 27
        versionCode 1
        versionName "1.0"

        // 2、启用Multidex
        multiDexEnabled true
    }
}

dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    // 3、配置Multidex依赖
    implementation 'com.quicklib:quicklib-multidex:1.0.1'
}
  • 4、项目Application配置

(1)如果不需要自定义Application,则直接引用MultiDexApplication

    
        ...
    

(2)如果需要自定义Application,并且没有继承其他第三方提供的Application
这时只需要自定义的Application继承Multidex的MultiDexApplication就可以了。

public class ZpApplication extends MultiDexApplication{
    // TODO 
}

(3)如果需要自定义Application,并且继承了其他第三方提供的Application
这时只需要在自定义Application重写attachBaseContext方法,调用MultiDex.install(this)即可

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

我们来看一下MultiDexApplication的源码,也只是在attachBaseContext中调用了MultiDex.install(this)

public class MultiDexApplication extends Application {
    public MultiDexApplication() {
    }

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

4、android 5.0 之后 (项目中minSdkVersion参数设置为21及以上)

Android 5.0 之后,安卓系统采用的是ART虚拟机,如果方法超过65535个,会自动分包,天然支持有多个dex文件,ART 在应用安装时执行预编译,将多个dex文件合并成一个oat文件执行。

所以minSdkVersion参数设置为21及以上时,就无需配置Multidex库

5、尽量避免64k问题

  • 去除没必要的依赖库
  • 精简用到的依赖库
  • 通过 ProGuard 移除未使用的代码

你可能感兴趣的:(Android 64K问题详解)