最近在学习开发Flutter项目时遇到了一个问题,具体的异常信息如下:

Flutter assets will be downloaded from https://storage.flutter-io.cn. Make sure you trust this source!
ERROR:D8: Cannot fit requested classes in a single dex file (# methods: 65853 > 65536)
com.android.builder.dexing.DexArchiveMergerException: Error while merging dex archives:
The number of method references in a .dex file cannot exceed 64K.
Learn how to resolve this issue at https://developer.android.com/tools/building/multidex.html
    at com.android.builder.dexing.D8DexArchiveMerger.getExceptionToRethrow(D8DexArchiveMerger.java:151)
    at com.android.builder.dexing.D8DexArchiveMerger.mergeDexArchives(D8DexArchiveMerger.java:138)
    at com.android.build.gradle.internal.tasks.DexMergingWorkAction.merge(DexMergingTask.kt:859)
    at com.android.build.gradle.internal.tasks.DexMergingWorkAction.run(DexMergingTask.kt:805)
    at com.android.build.gradle.internal.profile.ProfileAwareWorkAction.execute(ProfileAwareWorkAction.kt:74)
    at org.gradle.workers.internal.DefaultWorkerServer.execute(DefaultWorkerServer.java:63)
    at org.gradle.workers.internal.NoIsolationWorkerFactory$1$1.create(NoIsolationWorkerFactory.java:66)
    at org.gradle.workers.internal.NoIsolationWorkerFactory$1$1.create(NoIsolationWorkerFactory.java:62)
    at org.gradle.internal.classloader.ClassLoaderUtils.executeInClassloader(ClassLoaderUtils.java:100)
    at org.gradle.workers.internal.NoIsolationWorkerFactory$1.lambda$execute$0(NoIsolationWorkerFactory.java:62)
    at org.gradle.workers.internal.AbstractWorker$1.call(AbstractWorker.java:44)
    at org.gradle.workers.internal.AbstractWorker$1.call(AbstractWorker.java:41)
    at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:204)
    at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:199)
    at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66)
    at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59)
    at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:157)
    at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)
    at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:53)
    at org.gradle.internal.operations.DefaultBuildOperationExecutor.call(DefaultBuildOperationExecutor.java:73)
    at org.gradle.workers.internal.AbstractWorker.executeWrappedInBuildOperation(AbstractWorker.java:41)
    at org.gradle.workers.internal.NoIsolationWorkerFactory$1.execute(NoIsolationWorkerFactory.java:59)
    at org.gradle.workers.internal.DefaultWorkerExecutor.lambda$submitWork$2(DefaultWorkerExecutor.java:205)
    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
    at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.runExecution(DefaultConditionalExecutionQueue.java:187)
    at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.access$700(DefaultConditionalExecutionQueue.java:120)
    at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner$1.run(DefaultConditionalExecutionQueue.java:162)
    at org.gradle.internal.Factories$1.create(Factories.java:31)
    at org.gradle.internal.work.DefaultWorkerLeaseService.withLocks(DefaultWorkerLeaseService.java:249)
    at org.gradle.internal.work.DefaultWorkerLeaseService.runAsWorkerThread(DefaultWorkerLeaseService.java:109)
    at org.gradle.internal.work.DefaultWorkerLeaseService.runAsWorkerThread(DefaultWorkerLeaseService.java:114)
    at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.runBatch(DefaultConditionalExecutionQueue.java:157)
    at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.run(DefaultConditionalExecutionQueue.java:126)
    at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539)
    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
    at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
    at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:48)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
    at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: com.android.tools.r8.CompilationFailedException: Compilation failed to complete, position: null
    at Version.fakeStackEntry(Version_3.2.47.java:0)
    at com.android.tools.r8.internal.ci.a(R8_3.2.47_ebadcf1df6fbed6005a238b8399b2cd411e753b60758261060e399f9498872a5:68)
    at com.android.tools.r8.internal.ci.a(R8_3.2.47_ebadcf1df6fbed6005a238b8399b2cd411e753b60758261060e399f9498872a5:28)
    at com.android.tools.r8.internal.ci.a(R8_3.2.47_ebadcf1df6fbed6005a238b8399b2cd411e753b60758261060e399f9498872a5:27)
    at com.android.tools.r8.internal.ci.b(R8_3.2.47_ebadcf1df6fbed6005a238b8399b2cd411e753b60758261060e399f9498872a5:3)
    at com.android.tools.r8.D8.run(R8_3.2.47_ebadcf1df6fbed6005a238b8399b2cd411e753b60758261060e399f9498872a5:11)
    at com.android.builder.dexing.D8DexArchiveMerger.mergeDexArchives(D8DexArchiveMerger.java:136)
    ... 38 more
Caused by: com.android.tools.r8.internal.a: Cannot fit requested classes in a single dex file (# methods: 65853 > 65536)
    at com.android.tools.r8.internal.tQ.a(R8_3.2.47_ebadcf1df6fbed6005a238b8399b2cd411e753b60758261060e399f9498872a5:14)
    at com.android.tools.r8.internal.tQ.a(R8_3.2.47_ebadcf1df6fbed6005a238b8399b2cd411e753b60758261060e399f9498872a5:22)
    at com.android.tools.r8.internal.fZ.a(R8_3.2.47_ebadcf1df6fbed6005a238b8399b2cd411e753b60758261060e399f9498872a5:560)
    at com.android.tools.r8.internal.bZ.a(R8_3.2.47_ebadcf1df6fbed6005a238b8399b2cd411e753b60758261060e399f9498872a5:7)
    at com.android.tools.r8.internal.o2.a(R8_3.2.47_ebadcf1df6fbed6005a238b8399b2cd411e753b60758261060e399f9498872a5:383)
    at com.android.tools.r8.internal.o2.c(R8_3.2.47_ebadcf1df6fbed6005a238b8399b2cd411e753b60758261060e399f9498872a5:54)
    at com.android.tools.r8.D8.d(R8_3.2.47_ebadcf1df6fbed6005a238b8399b2cd411e753b60758261060e399f9498872a5:763)
    at com.android.tools.r8.D8.b(R8_3.2.47_ebadcf1df6fbed6005a238b8399b2cd411e753b60758261060e399f9498872a5:1)
    at com.android.tools.r8.internal.ci.a(R8_3.2.47_ebadcf1df6fbed6005a238b8399b2cd411e753b60758261060e399f9498872a5:24)
    ... 41 more




FAILURE: Build failed with an exception.


* What went wrong:
Execution failed for task ':app:mergeExtDexDebug'.
> A failure occurred while executing com.android.build.gradle.internal.tasks.DexMergingTaskDelegate
   > There was a failure while executing work items
      > A failure occurred while executing com.android.build.gradle.internal.tasks.DexMergingWorkAction
         > com.android.builder.dexing.DexArchiveMergerException: Error while merging dex archives:
           The number of method references in a .dex file cannot exceed 64K.
           Learn how to resolve this issue at https://developer.android.com/tools/building/multidex.html


* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.


* Get more help at https://help.gradle.org


BUILD FAILED in 33s

在异常信息中让我们去这个地方 https://developer.android.com/tools/building/multidex.html 解决问题。(以上地址已经失效了,新的地址是:https://developer.android.com/build/multidex
查阅资料后知道了,Android 5.0 及更高版本的 MultiDex 支持,而低版本需要手动操作配置一些东西。

  • Android 5.0 之前版本的 MultiDex 支持
    Android 5.0(API 级别 21)之前的平台版本使用 Dalvik 运行时执行应用代码。默认情况下,Dalvik 将应用限制为每个 APK 只能使用一个 classes.dex 字节码文件。为了绕过这一限制,您可以向模块级 build.gradle 文件中添加 MultiDex 库:
...
dependencies {
    def multidex_version = "2.0.1"
    implementation "androidx.multidex:multidex:$multidex_version"
}
...

如需查看此库的当前版本,请参阅版本页面中有关 MultiDex 的信息。
如果您使用的不是 AndroidX,请改为添加以下已弃用的支持库依赖项:

...
dependencies {
    implementation 'com.android.support:multidex:1.0.3'
}
...
  • Android 5.0 及更高版本的 MultiDex 支持
    Android 5.0(API 级别 21)及更高版本使用名为 ART 的运行时,它本身支持从 APK 文件加载多个 DEX 文件。ART 在应用安装时执行预编译,这会扫描查找 classesN.dex 文件,并将它们编译成单个 .oat 文件,以供 Android 设备执行。因此,如果您的 minSdkVersion 为 21 或更高版本,系统会默认启用 MultiDex,并且您不需要 MultiDex 库。

经过网上的一番资料查询,得知是项目中android/app/build.gradle文件中defaultConfig的minSdkVersion太低。

...
android {
    
    ...
    
    defaultConfig {
        // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
        applicationId "com.baikeyang.blog"
        // You can update the following values to match your application needs.
        // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
        minSdkVersion flutter.minSdkVersion
        targetSdkVersion flutter.targetSdkVersion
        versionCode flutterVersionCode.toInteger()
        versionName flutterVersionName
    }

    ...
    
}

    ...
    

当找到项目中对应的位置,发现defaultConfig的minSdkVersion配置的是flutter.minSdkVersion的值,并没有直接写明minSdkVersion的值
那么问题来了,flutter.minSdkVersion这个对应的版本到底是多少呢?
继续查询一番,找到了flutter.minSdkVersion的版本信息。
前往自己的FlutterSDK目录中找到flutter.gradle文件:[盘符]:\[flutterSDK位置]\packages\flutter_tools\gradle\flutter.gradle,在文件的36行就可以找到Flutter默认的minSdkVersion版本是多少,同时还可以知道compileSdkVersion、targetSdkVersion 分别是多少。

...
/** For apps only. Provides the flutter extension used in app/build.gradle. */
class FlutterExtension {
    /** Sets the compileSdkVersion used by default in Flutter app projects. */
    static int compileSdkVersion = 33

    /** Sets the minSdkVersion used by default in Flutter app projects. */
    static int minSdkVersion = 16

    /** Sets the targetSdkVersion used by default in Flutter app projects. */
    static int targetSdkVersion = 33

    /**
     * Sets the ndkVersion used by default in Flutter app projects.
     * Chosen as default version of the AGP version below as found in
     * https://developer.android.com/studio/projects/install-ndk#default-ndk-per-agp
     */
    static String ndkVersion = "23.1.7779620"

    /**
     * Specifies the relative directory to the Flutter project directory.
     * In an app project, this is ../.. since the app's build.gradle is under android/app.
     */
    String source

    /** Allows to override the target file. Otherwise, the target is lib/main.dart. */
    String target
}
...

知道了minSdkVersion值是16。为了不影响FlutterSDK,我这里并没有直接在这里修改。而是返回项目中修改了项目中android/app/build.gradle文件中defaultConfig的minSdkVersion

defaultConfig {
    // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
    applicationId "com.baikeyang.blog"
    // You can update the following values to match your application needs.
    // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
    minSdkVersion 21
    targetSdkVersion flutter.targetSdkVersion
    versionCode flutterVersionCode.toInteger()
    versionName flutterVersionName
}

重新编译运行项目,编译启动正常。

标签: Flutter, ERROR:D8, Cannot fit requested classes in a single dex file

添加新评论