如何正确减少app方法计数(低于dex-limit)

时间:2017-12-14 16:15:22

标签: android dependencies build.gradle android-multidex

我启动了一个新的应用程序,它大量使用了firebase功能以及支持库。我很快就达到了65k dex限制,即使我没有理由因为应用程序的简单性而应该在那里。我知道我需要排除某些我没用的依赖项,所以我一直在使用gradlew app:dependencies来分析依赖项,并且不止一次地提取所提取的内容或者我不需要的内容。

尽管有exclude吨,但我无法大幅度减少方法(仅3%)。我只是坚持多dex?如果没有,我该如何有效地减少方法数呢?

更多信息:

  • minSdk 19

这是build.gradle依赖项块和gradlew app:dependencies output之前/之后。我很乐意发布每个库有多少方法的dexcount文本输出,如果有帮助的话。我可以说,方法计数的最大贡献者是支持库和com.google.common。*和com.google.android.gms。*

瘦身前

  • app-debug.apk中的总方法:67707(使用率为103.31%)

瘦身后

  • app-debug.apk中的总方法:65852(已使用100.48%)

之前:build.gradle依赖阻止(不排除)

dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    implementation 'com.android.support:multidex:1.0.2'
    implementation "com.android.support:appcompat-v7:$supportLibraryVersion"
    implementation "com.android.support:recyclerview-v7:$supportLibraryVersion"
    implementation "com.android.support:design:$supportLibraryVersion"
    implementation 'com.android.support.constraint:constraint-layout:1.0.2'
    implementation "com.android.support:cardview-v7:$supportLibraryVersion"
    implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'
    implementation 'io.reactivex.rxjava2:rxjava:2.1.5'
    implementation('com.oakwoodsc.rxfirestore:rxfirestore-debug:1.0@aar') {
        exclude group: 'io.reactivex.rxjava2', module: 'rxandroid'
        exclude group: 'io.reactivex.rxjava2', module: 'rxjava'
    }
    implementation 'com.firebaseui:firebase-ui-auth:3.1.0' // Remove once custom version
    implementation "com.google.android.gms:play-services-location:$firebaseVersion"
    implementation "com.google.firebase:firebase-firestore:$firebaseVersion"
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.1'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
}

之前:gradlew app:dependencies输出

很多重复!

+--- com.google.firebase:firebase-core:11.4.2
|    \--- com.google.firebase:firebase-analytics:11.4.2
|         +--- com.google.android.gms:play-services-basement:11.4.2
|         |    +--- com.android.support:support-v4:25.2.0 -> 26.1.0
|         |    |    +--- com.android.support:support-compat:26.1.0
|         |    |    |    +--- com.android.support:support-annotations:26.1.0
|         |    |    |    \--- android.arch.lifecycle:runtime:1.0.0
|         |    |    |         +--- android.arch.lifecycle:common:1.0.0
|         |    |    |         \--- android.arch.core:common:1.0.0
|         |    |    +--- com.android.support:support-media-compat:26.1.0
|         |    |    |    +--- com.android.support:support-annotations:26.1.0
|         |    |    |    \--- com.android.support:support-compat:26.1.0 (*)
|         |    |    +--- com.android.support:support-core-utils:26.1.0
|         |    |    |    +--- com.android.support:support-annotations:26.1.0
|         |    |    |    \--- com.android.support:support-compat:26.1.0 (*)
|         |    |    +--- com.android.support:support-core-ui:26.1.0
|         |    |    |    +--- com.android.support:support-annotations:26.1.0
|         |    |    |    \--- com.android.support:support-compat:26.1.0 (*)
|         |    |    \--- com.android.support:support-fragment:26.1.0
|         |    |         +--- com.android.support:support-compat:26.1.0 (*)
|         |    |         +--- com.android.support:support-core-ui:26.1.0 (*)
|         |    |         \--- com.android.support:support-core-utils:26.1.0 (*)
|         |    \--- com.google.android.gms:play-services-basement-license:11.4.2
|         +--- com.google.firebase:firebase-common:11.4.2
|         |    +--- com.google.android.gms:play-services-basement:11.4.2 (*)
|         |    +--- com.google.android.gms:play-services-tasks:11.4.2
|         |    |    +--- com.google.android.gms:play-services-basement:11.4.2 (*)
|         |    |    \--- com.google.android.gms:play-services-tasks-license:11.4.2
|         |    \--- com.google.firebase:firebase-common-license:11.4.2
|         +--- com.google.firebase:firebase-analytics-impl:11.4.2
|         |    +--- com.google.android.gms:play-services-basement:11.4.2 (*)
|         |    +--- com.google.firebase:firebase-iid:11.4.2
|         |    |    +--- com.google.android.gms:play-services-basement:11.4.2 (*)
|         |    |    +--- com.google.firebase:firebase-common:11.4.2 (*)
|         |    |    \--- com.google.firebase:firebase-iid-license:11.4.2
|         |    +--- com.google.firebase:firebase-common:11.4.2 (*)
|         |    +--- com.google.android.gms:play-services-tasks:11.4.2 (*)
|         |    \--- com.google.firebase:firebase-analytics-impl-license:11.4.2
|         \--- com.google.firebase:firebase-analytics-license:11.4.2
+--- com.android.support:multidex:1.0.2
+--- com.android.support:appcompat-v7:26.1.0
|    +--- com.android.support:support-annotations:26.1.0
|    +--- com.android.support:support-v4:26.1.0 (*)
|    +--- com.android.support:support-vector-drawable:26.1.0
|    |    +--- com.android.support:support-annotations:26.1.0
|    |    \--- com.android.support:support-compat:26.1.0 (*)
|    \--- com.android.support:animated-vector-drawable:26.1.0
|         +--- com.android.support:support-vector-drawable:26.1.0 (*)
|         \--- com.android.support:support-core-ui:26.1.0 (*)
+--- com.android.support:recyclerview-v7:26.1.0
|    +--- com.android.support:support-annotations:26.1.0
|    +--- com.android.support:support-compat:26.1.0 (*)
|    \--- com.android.support:support-core-ui:26.1.0 (*)
+--- com.android.support:design:26.1.0
|    +--- com.android.support:support-v4:26.1.0 (*)
|    +--- com.android.support:appcompat-v7:26.1.0 (*)
|    +--- com.android.support:recyclerview-v7:26.1.0 (*)
|    \--- com.android.support:transition:26.1.0
|         +--- com.android.support:support-annotations:26.1.0
|         \--- com.android.support:support-v4:26.1.0 (*)
+--- com.android.support.constraint:constraint-layout:1.0.2 -> 1.1.0-beta1
|    \--- com.android.support.constraint:constraint-layout-solver:1.1.0-beta1
+--- com.android.support:cardview-v7:26.1.0
|    \--- com.android.support:support-annotations:26.1.0
+--- io.reactivex.rxjava2:rxandroid:2.0.1
|    \--- io.reactivex.rxjava2:rxjava:2.0.1 -> 2.1.5
|         \--- org.reactivestreams:reactive-streams:1.0.1
+--- io.reactivex.rxjava2:rxjava:2.1.5 (*)
+--- com.oakwoodsc.rxfirestore:rxfirestore-debug:1.0
+--- com.firebaseui:firebase-ui-auth:3.1.0
|    +--- com.android.support:design:26.1.0 (*)
|    +--- com.android.support:customtabs:26.1.0
|    |    +--- com.android.support:support-compat:26.1.0 (*)
|    |    \--- com.android.support:support-annotations:26.1.0
|    +--- com.android.support.constraint:constraint-layout:1.1.0-beta1 (*)
|    +--- com.google.firebase:firebase-auth:11.4.2
|    |    +--- com.google.android.gms:play-services-base:11.4.2
|    |    |    +--- com.google.android.gms:play-services-basement:11.4.2 (*)
|    |    |    +--- com.google.android.gms:play-services-tasks:11.4.2 (*)
|    |    |    \--- com.google.android.gms:play-services-base-license:11.4.2
|    |    +--- com.google.android.gms:play-services-basement:11.4.2 (*)
|    |    +--- com.google.firebase:firebase-common:11.4.2 (*)
|    |    +--- com.google.android.gms:play-services-tasks:11.4.2 (*)
|    |    \--- com.google.firebase:firebase-auth-license:11.4.2
|    +--- com.google.android.gms:play-services-auth:11.4.2
|    |    +--- com.google.android.gms:play-services-auth-api-phone:11.4.2
|    |    |    +--- com.google.android.gms:play-services-base:11.4.2 (*)
|    |    |    +--- com.google.android.gms:play-services-basement:11.4.2 (*)
|    |    |    +--- com.google.android.gms:play-services-tasks:11.4.2 (*)
|    |    |    \--- com.google.android.gms:play-services-auth-api-phone-license:11.4.2
|    |    +--- com.google.android.gms:play-services-auth-base:11.4.2
|    |    |    +--- com.google.android.gms:play-services-base:11.4.2 (*)
|    |    |    +--- com.google.android.gms:play-services-basement:11.4.2 (*)
|    |    |    +--- com.google.android.gms:play-services-tasks:11.4.2 (*)
|    |    |    \--- com.google.android.gms:play-services-auth-base-license:11.4.2
|    |    +--- com.google.android.gms:play-services-base:11.4.2 (*)
|    |    +--- com.google.android.gms:play-services-basement:11.4.2 (*)
|    |    +--- com.google.android.gms:play-services-tasks:11.4.2 (*)
|    |    \--- com.google.android.gms:play-services-auth-license:11.4.2
|    \--- com.android.support:cardview-v7:26.1.0 (*)
+--- com.google.android.gms:play-services-location:11.4.2
|    +--- com.google.android.gms:play-services-base:11.4.2 (*)
|    +--- com.google.android.gms:play-services-basement:11.4.2 (*)
|    +--- com.google.android.gms:play-services-tasks:11.4.2 (*)
|    \--- com.google.android.gms:play-services-location-license:11.4.2
\--- com.google.firebase:firebase-firestore:11.4.2
     +--- com.google.android.gms:play-services-basement:11.4.2 (*)
     +--- com.google.firebase:firebase-common:11.4.2 (*)
     +--- com.google.android.gms:play-services-tasks:11.4.2 (*)
     +--- com.squareup.okhttp:okhttp:2.7.2
     |    \--- com.squareup.okio:okio:1.6.0
     \--- com.google.guava:guava:20.0

之后:build.gradle依赖块(全部排除)

dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    implementation("com.google.android.gms:play-services-base:$playServicesVersion") {
        exclude group: "com.android.support", module: "support-v4"
    }
    implementation 'com.android.support:multidex:1.0.2'
    implementation "com.android.support:design:$supportLibraryVersion"
    implementation("com.firebaseui:firebase-ui-auth:3.1.0") {  // Remove once custom version
        exclude group: "com.google.android.gms", module: "play-services-base"
        exclude group: "com.google.android.gms", module: "play-services-basement"
        exclude group: "com.google.android.gms", module: "play-services-tasks"
        exclude group: "com.android.support", module: "design"
        exclude group: "com.android.support", module: "support-compat"
        exclude group: "com.android.support", module: "support-annotations"
        exclude group: "com.android.support", module: "cardview-v7"
    }
    implementation("com.android.support:cardview-v7:$supportLibraryVersion") {
        exclude group: "com.android.support", module: "support-annotations"
    }
    implementation('com.oakwoodsc.rxfirestore:rxfirestore-debug:1.0@aar') {
        exclude group: 'io.reactivex.rxjava2', module: 'rxandroid'
        exclude group: 'io.reactivex.rxjava2', module: 'rxjava'
    }
    implementation("com.google.android.gms:play-services-location:$playServicesVersion") {
        exclude group: "com.google.android.gms", module: "play-services-base"
        exclude group: "com.google.android.gms", module: "play-services-tasks"
        exclude group: "com.google.android.gms", module: "play-services-basement"
    }
    implementation("com.google.firebase:firebase-firestore:$playServicesVersion") {
        exclude group: "com.google.android.gms", module: "play-services-basement"
        exclude group: "com.google.android.gms", module: "play-services-tasks"
    }
    implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'
    implementation 'io.reactivex.rxjava2:rxjava:2.1.5'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.1'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
}

之后:gradlew app:dependencies输出

少重复...

+--- com.google.android.gms:play-services-base:11.4.2
|    +--- com.google.android.gms:play-services-basement:11.4.2
|    |    \--- com.google.android.gms:play-services-basement-license:11.4.2
|    +--- com.google.android.gms:play-services-tasks:11.4.2
|    |    +--- com.google.android.gms:play-services-basement:11.4.2 (*)
|    |    \--- com.google.android.gms:play-services-tasks-license:11.4.2
|    \--- com.google.android.gms:play-services-base-license:11.4.2
+--- com.android.support:multidex:1.0.2
+--- com.android.support:design:26.1.0
|    +--- com.android.support:support-v4:26.1.0
|    |    +--- com.android.support:support-compat:26.1.0
|    |    |    +--- com.android.support:support-annotations:26.1.0
|    |    |    \--- android.arch.lifecycle:runtime:1.0.0
|    |    |         +--- android.arch.lifecycle:common:1.0.0
|    |    |         \--- android.arch.core:common:1.0.0
|    |    +--- com.android.support:support-media-compat:26.1.0
|    |    |    +--- com.android.support:support-annotations:26.1.0
|    |    |    \--- com.android.support:support-compat:26.1.0 (*)
|    |    +--- com.android.support:support-core-utils:26.1.0
|    |    |    +--- com.android.support:support-annotations:26.1.0
|    |    |    \--- com.android.support:support-compat:26.1.0 (*)
|    |    +--- com.android.support:support-core-ui:26.1.0
|    |    |    +--- com.android.support:support-annotations:26.1.0
|    |    |    \--- com.android.support:support-compat:26.1.0 (*)
|    |    \--- com.android.support:support-fragment:26.1.0
|    |         +--- com.android.support:support-compat:26.1.0 (*)
|    |         +--- com.android.support:support-core-ui:26.1.0 (*)
|    |         \--- com.android.support:support-core-utils:26.1.0 (*)
|    +--- com.android.support:appcompat-v7:26.1.0
|    |    +--- com.android.support:support-annotations:26.1.0
|    |    +--- com.android.support:support-v4:26.1.0 (*)
|    |    +--- com.android.support:support-vector-drawable:26.1.0
|    |    |    +--- com.android.support:support-annotations:26.1.0
|    |    |    \--- com.android.support:support-compat:26.1.0 (*)
|    |    \--- com.android.support:animated-vector-drawable:26.1.0
|    |         +--- com.android.support:support-vector-drawable:26.1.0 (*)
|    |         \--- com.android.support:support-core-ui:26.1.0 (*)
|    +--- com.android.support:recyclerview-v7:26.1.0
|    |    +--- com.android.support:support-annotations:26.1.0
|    |    +--- com.android.support:support-compat:26.1.0 (*)
|    |    \--- com.android.support:support-core-ui:26.1.0 (*)
|    \--- com.android.support:transition:26.1.0
|         +--- com.android.support:support-annotations:26.1.0
|         \--- com.android.support:support-v4:26.1.0 (*)
+--- com.firebaseui:firebase-ui-auth:3.1.0
|    +--- com.android.support:customtabs:26.1.0
|    +--- com.android.support.constraint:constraint-layout:1.1.0-beta1
|    |    \--- com.android.support.constraint:constraint-layout-solver:1.1.0-beta1
|    +--- com.google.firebase:firebase-auth:11.4.2
|    |    +--- com.google.firebase:firebase-common:11.4.2
|    |    |    \--- com.google.firebase:firebase-common-license:11.4.2
|    |    \--- com.google.firebase:firebase-auth-license:11.4.2
|    \--- com.google.android.gms:play-services-auth:11.4.2
|         +--- com.google.android.gms:play-services-auth-api-phone:11.4.2
|         |    \--- com.google.android.gms:play-services-auth-api-phone-license:11.4.2
|         +--- com.google.android.gms:play-services-auth-base:11.4.2
|         |    \--- com.google.android.gms:play-services-auth-base-license:11.4.2
|         \--- com.google.android.gms:play-services-auth-license:11.4.2
+--- com.android.support:cardview-v7:26.1.0
+--- com.oakwoodsc.rxfirestore:rxfirestore-debug:1.0
+--- com.google.android.gms:play-services-location:11.4.2
|    \--- com.google.android.gms:play-services-location-license:11.4.2
+--- com.google.firebase:firebase-firestore:11.4.2
|    +--- com.google.firebase:firebase-common:11.4.2 (*)
|    +--- com.squareup.okhttp:okhttp:2.7.2
|    |    \--- com.squareup.okio:okio:1.6.0
|    \--- com.google.guava:guava:20.0
+--- io.reactivex.rxjava2:rxandroid:2.0.1
|    \--- io.reactivex.rxjava2:rxjava:2.0.1 -> 2.1.5
|         \--- org.reactivestreams:reactive-streams:1.0.1
\--- io.reactivex.rxjava2:rxjava:2.1.5 (*)

2 个答案:

答案 0 :(得分:1)

首先,您不需要所有这些exclude。如果两个依赖项使用com.android.support:support-v4:26.1.0,则只包含一次。它列出两次,以便您可以看到谁依赖它。

您可能需要考虑的一个选项是turning on ProGuard。这将删除任何未使用的代码,包括库代码。在你的情况下,它可能会让你低于65k的限制。

要使用它,请在build.gradle中设置:     发布 {         minifyEnabled是的         proguardFiles getDefaultProguardFile(' proguard-android.txt'),                 ' proguard-rules.pro'     }

您需要创建proguard-rules.pro并使用特定于您应用的指令填充它。请务必查看完整的文档,了解您可能需要包含的内容。

虽然没有ProGuard可以保持在65k以下的限制,但大多数中等复杂度的应用程序会相当快地超过它,我发现避免像AppCompat这样的库以保持在65k以下的限制是通常比工作更多的工作。

即使使用ProGuard,某些应用也会遇到65k的限制。其他应用可能由于某种原因不想使用ProGuard。在这些情况下,您最好选择enable multidex,这样可以超过65k的限制。

答案 1 :(得分:1)

Proguard是解决问题的关键。确保您的应用build.gradle 文件在buildtypes下具有以下内容

buildTypes {
    //debug
    //staging
    release {
        minifyEnabled true
        shrinkResources true
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
}

在我的情况下,我的发布版本,缩小代码,缩小资源,最重要的使用proguard来减少其他库带来的代码膨胀。您可以复制代码proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

关于David East对Proguard的好处,请观看这​​篇真棒short video

此外,如果您还没有查看Proguard文档