多个 R.java 中的冗余资源引用导致 Dax Index OverflowException

Redundant resource referances in multiple R.java causes DexIndexOverflowException

我有多个库项目,它们都依赖于支持库。我的应用程序依赖于这些多个库项目。每个图书馆项目都在其 R.java 文件中包含对支持图书馆资源的引用。由于冗余,这会增加字段 ID 计数。

我的应用获得

DexIndexOverflowException: field ID not in [0, 0xffff]: 65536

因为这个冗余的 R.java 引用。

因此,我的应用程序有 47k 个方法,而 65k 个字段 ID。

编辑:

我不会使用 multi-dex,它不能解决我的问题。我想剃掉多余的字段 ID。

问题不在于如何解决该问题,而在于如何摆脱多余的字段 ID。使用 multi-dex 不会删除冗余字段 ID。

DexIndexOverflowException: field ID not in [0, 0xffff]: 65536

  • Android 已预定义上限 limit of Methods of 65536.

什么时候?

The size of the DEX file’s method index is 16 bit, so it means that 65536 represents the total number of references that can be invoked by the code within a single DEX file. If overcome then arise this error.

一旦您开始包含足够的库导致达到 64K 方法限制,您需要删除无关的依赖项。

怎么样?不使用 multiDex

ProGuard optimizes the bytecode, removes unused code instructions, and obfuscates the remaining classes, fields, and methods with short names.Resource shrinking is available with the Android plugin for Gradle, which removes unused resources from your packaged app, including unused resources in code libraries. It works in conjunction with code shrinking such that once unused code has been removed, any resources no longer referenced can be safely removed as well .

如何启用 Proguard

minifyEnabled true 添加到 build.gradle 文件中适当的构建类型。

android {
    buildTypes {
        release { //You can add this in debug mode
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'),
                    'proguard-rules.pro'
        }
    }

}

注意

  1. getDefaultProguardFile('proguard-android.txt')方法获取 来自 Android SDK 的默认 ProGuard 设置 tools->proguard->folder .

  2. proguard-rules.pro 文件是您可以添加自定义 ProGuard 规则的地方。

资源缩减

Resource shrinking works only in conjunction with code shrinking. After the code shrinker removes all unused code, the resource shrinker can identify which resources the app still uses.

buildTypes {
    release {
              minifyEnabled true
              shrinkResources true  //You can add this in debug mode
    }
}

就像@intellij-amiya 的回答一样,使用multidexproguard 将解决您的问题,我个人推荐这样做。

如果您不想遵循该方法,您可以手动排除重复的依赖项。

在您的终端中执行以下命令以查找重复的依赖项。

./gradlew :app:dependencies --configuration compile

或者如果你在 windows,

gradlew.bat :app:dependencies --configuration compile

:app 更改为您的项目名称。

让我们假设您的 gradle 依赖项是这样的:

compile 'com.android.support:support-compat:26.+'
compile 'com.android.support:support-fragment:26.+'

您将得到如下输出:

+--- com.android.support:support-compat:26.+ -> 26.0.0-alpha1
|    \--- com.android.support:support-annotations:26.0.0-alpha1
\--- com.android.support:support-fragment:26.+ -> 26.0.0-alpha1
     +--- com.android.support:support-compat:26.0.0-alpha1 (*)
     +--- com.android.support:support-core-ui:26.0.0-alpha1
     |    +--- com.android.support:support-annotations:26.0.0-alpha1
     |    \--- com.android.support:support-compat:26.0.0-alpha1 (*)
     \--- com.android.support:support-core-utils:26.0.0-alpha1
          +--- com.android.support:support-annotations:26.0.0-alpha1
          \--- com.android.support:support-compat:26.0.0-alpha1 (*)

并且可以看到标有(*)的依赖,可以排除这些依赖。你可以看到 support-compat 是重复的,并且通过这样的编辑来排除它:

compile ('com.android.support:support-fragment:26.+') {
    exclude module: 'support-compat'
}

重复此操作,直到计数低于 64k

现在最难的部分还在。

根据我的经验,排除某些依赖项可能会导致构建失败、运行时异常等。因此您需要检查您的应用程序是否正常运行。

希望对您有所帮助。

我的问题通过在模块 build.gradle 中添加 "multiDexEnabled true" 解决了。

android {
          ...
          defaultConfig {
                          ...
                          multiDexEnabled true
                         }
         }