Android开发经验谈Android开发Android技术知识

Android - 使用MultiDex解决64K问题

2017-12-28  本文已影响237人  Allens_Jiang
老婆保佑,代码无BUG

目录


一:什么是64K

问题描述

Error:The number of method references in a .dex file cannot exceed 64K.
Error:Execution failed for task ':app:transformClassesWithDexForRelease'.

即方法数目超过65535

二:使用MultiDex解决64K

Multidex支持到Android 5.0之前

安卓系统采用的是Dalvik虚拟机,采用的是JIT技术(Just-in-time compilation,即时编译,运行时编译DEX字节码文件,这也是以前为什么安卓手机用户总是诟病Android系统比iOS系统运行卡顿的原因),限制每个APK文件只能包含一个DEX文件(即classes.dex)。为了绕开这个限制,Google给我们提供了multidex support library兼容包,帮助我们实现应用程序加载多个DEX文件,并且这个兼容包作为程序的主DEX文件,管理者其他DEX文件的访问。

注意:由于Instant Run机制利用的就是multidex原理,当项目中minSdkVersion参数设置为20或者更小,并且运行在Android 4.4 (API level 20)或更低版本的设备中时,Instant Run将失效。

5.0之后

安卓系统改用了ART虚拟机(Android RunTime),采用的是OAT技术(Ahead-of-time,预编译,在应用安装的时候扫描应用中的所有DEX文件,并编译成一个.oat格式的文件供安卓设备执行,所以相比Dalvik虚拟机下的应用,安装时间较长)。因此可以理解为,使用ART虚拟机下的安卓系统自动支持APK文件中多个DEX的加载。

注意:使用Instant Run时,如果项目中的minSdkVersion参数设为21或更高版本,Android Studio编译运行时会自动使应用支持multidex。但Instant Run仅仅作用于debug版本,我们依然需要给release版本配置multidex来避开64K方法数的限制。

三:配置MultiDex

配置build.gradle
android {

    compileSdkVersion 21
    buildToolsVersion "21.1.0"

    defaultConfig {
        ...

        // Enabling multidex support.
        multiDexEnabled true
    }
    ...
}

dependencies {
  compile 'com.android.support:multidex:1.0.0'
}

配置AndroidManifest.xml
<?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>
  @Override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);
        MultiDex.install(this) ;
    }

四:productFlavors

初次引入MultiDex 需要很长的时间,为减少开发阶段,运行时间,使用productFlavors

android {
    //定义不同的flavors
    productFlavors {
       //开发阶段
        dev {
           //运行在Android 5.0以上版本的设备中,使用ART-supported格式生成multidex的速度要快得多
            minSdkVersion 21
        }
        prod {
          //实际支持的最低版本
            minSdkVersion 14
        }
    }
}

写在最后

这个是一个解决方案,但是呢,我觉得,在写项目的时候,就要有意识去避免这么问题,不要过多的映入第三方,不同的依赖库就删了,还能较少包的体积,当然还有其他的解决方案,比如插件化,这个放在后面专门的讲

上一篇下一篇

猜你喜欢

热点阅读