MultiDex的介绍和配置并提高构建效率

本文探讨了Android应用遭遇的64K方法数限制问题及其解决方案。通过采用MultiDex技术,可在不同版本的Android系统上有效扩展应用程序的规模。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

MultiDex

最近优化升级项目,终于报了64K方法限制数的问题,顺便记录一下解决的方案;

64K限制的原因

Android APK文件本质是一个压缩文件,它里面包含了classes.dex文件是可执行的Dalvik(安卓虚拟机)字节码文件,这个 .dex文件中存放的是所有编译后的Java代码。Dalvik可执行文件规范限制了单个dex文件最多能饮用的方法数是65536个,其中还包含了Android Framework、APP引用的第三方函数库以及自身的方法(感觉这是个设计的失误);

使用 MultiDex解决64K限制

Android5.0之前

在5.0之前,系统使用的是Dalvik虚拟机来执行Android应用,Dalvik为每个APK只生成一个dex文件,为了避免超过64K的限制,我们只能将一个dex拆分成若干个dex,类似于classes.dex,classes2.dex,classes3.dex,应用启动后,程序会先加载主dex,然后依次加在其他的dex;Google推出了一个名为MultiDex Support Library的函数库,可以在 /extras/android/support/mulidex/下找到这个库;

Android5.0之后

5.0之后系统开始使用ART的虚拟机来代替Dalvik的虚拟机,ART天然支持APK加载多个dex文件,它可以直接扫描所有的dex文件并将他们编译成一个oat文件,引用直接加载oat而并非去一个一个加载dex文件;

使用 MultiDex配置

MultiDex的配置主要是在Gradle文件中进行的,但是不仅需要配置Module中的Gradle文件,还需要配置项目根目录下的Gradle文件。
首先,我们先来配置Module中的Gradle文件,文件中的代码如下:

apply plugin: 'com.android.application'

android {
    // productFlavors是为了避免每次运行都把DEX重新加载一遍而设置的两套运行配置
    productFlavors {
        dev {
            minSdkVersion 21
        }
        prod {
            minSdkVersion 14
        }
    }
    compileSdkVersion 24
    buildToolsVersion "24.0.2"
    defaultConfig {
        applicationId "com.example.itgungnir.testmultidex"
        minSdkVersion 11
        targetSdkVersion 24
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        // 设置MultiDex可用
        multiDexEnabled true
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    // 保证其他的lib没有被preDex
    dexOptions {
        preDexLibraries = false
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.android.support:appcompat-v7:24.2.1'
    testCompile 'junit:junit:4.12'
    // MultiDex的依赖
    compile 'com.android.support:multidex:1.0.1'
}

配置完Module下的Gradle文件,接下来配置Project下的Gradle文件。文件中的代码如下:

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.2.0'
    }
}

allprojects {
    repositories {
        jcenter()
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

// 保证dex_files文件中指定的文件都加载到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/dex_files".toString()
    }
}

可以看到,这里主要添加了afterEvaluate代码块,最后一行中的dex_files是一个.txt文件,其中存放着想要默认加载到MainDex中的所有文件。这个dex_files文件是和这个Gradle文件在同一级目录下,以下是dex_files.txt文件中的代码(大家可以根据需要添加):

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$1/class
android/support/multidex/MultiDexExtractor/class
android/support/multidex/ZipUtil$CentralDirectory/class
android/support/multidex/ZipUtil/class

最后,需要在项目的Application文件中注入MultiDex,代码如下:

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

    @Override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);
        // 将MultiDex注入到项目中
        // attachBaseContext的方法是在onCreate之前执行的。是开发者可以控制应用最早执行的方法
        MultiDex.install(this);
    }
}

最后记得在Manifest中配置Application

提高构建效率

在项目中加入MultiDex后,你点了构建按钮后,发现速度大不如从前;如果是超大型的应用,那速度可想而知;为了减少开发阶段由于倒入MultiDex所增加的构建时间,我们可以在工程的主模块build.gradle文件中使用productFlavors来构建两个flavor,一个开发用一个生产用;

android{
      productFlavors{
             dev{
                    //开发阶段的嘴笑版本
                    minSdkVersion 21
             }
             prod{
                    //app实际的最小版本
                    minSdkVersion 14
             }
      }
}

上面的配置完成以后,可以使用devDebug variant来构建我们的应用,他会结合dev的productFlavor和debug的buildType的配置,也就是最终生成的APK不会使用ProGuard;

接下来我们介绍如何使用devDebug这个Build Variant,可以使用命令行:

./gradlew installDevDebug

在Android Studio中,点击右侧的Build Variant,可以打开对应的module中选择devDebug即可

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值