Configure Apps with Over 64K Methods

翻译自:https://developer.android.com/studio/build/multidex.html?hl=zh-cn

随着Android平台的发展,Android应用的大小也变得越来越大。当你的应用和依赖库达到某一个大小时,你会遇到构建错误,提示你的应用达到了Android应用构建结构的一个限制,早期构建系统的版本会报如下的错误:

Conversion to Dalvik format failed:
Unable to execute dex: method ID not in [0, 0xffff]: 65536

最近的Android构建系统展示一种不同的错误,但是是同一种问题的表象:

trouble writing output:
Too many field references: 131000; max is 65536.
You may try using –multi-dex option.

这两种错误都展示了一个相同的数字:65536。这个数字很重要,他表示了一个单独的dex字符码文件可以调用的方法的总数。如果你构建Android应用时收到了这个错误,那么恭喜你,你有很多的代码。这个文件告诉你如何越过这个限制,继续构建你的应用。

Note: The guidance provided in this document supersedes the guidance given in the Android Developers blog post Custom Class Loading in Dalvik.

关于64K的依赖限制

Android的apk文件包含可执行的字符码文件,这些文件以dex格式的形式存在,包含了用来运行应用的编译代码。dex文件的规范限制了一个单独的dex文件所有可依赖的方法数为65536,包含了Android框架方法、依赖库方法、和你自己代码里面的方法。在计算机科学的概念里,这个词语K表示1024,或者是2^10。因为65536是64x1024,这个限制也被称作64k方法限制。
越过这个限制需要你配置应用的构建过程,来产生多个dex文件,被称作多dex配置。

5.0以前的多dex支持

Android5.0(API 21)以前的版本使用Dalvik运行时来运行应用代码。默认情况下,Dalvik限制每个应用一个单独的dex文件。为了越过这个限制,你可以使用多dex依赖库multidex support library,变成应用中主dex文件的一部分,管理添加dex文件和他们包括的代码。

Note: If your project is configured for multidex with minSdkVersion 20 or lower, and you deploy to target devices running Android 4.4 (API level 20) or lower, Android Studio disables Instant Run.

5.0及以上版本的多dex支持

Android5.0(API 21)及以上使用ART,原生就支持从apk中多dex文件加载。ART在应用安装的时候采用预编译,会扫描所有的dex文件,然后把他们编译到一个oat文件中,让Android设备执行。

Note: While using Instant Run, Android Studio automatically configures your app for multidex when your app’s minSdkVersion is set to 21 or higher. Because Instant Run only works with the debug version of your app, you still need to configure your release build for multidex to avoid the 64K limit.

避免64K限制

在配置你的应用可以使用64k或更多的方法数之前,你应该减少你代码里面方法的个数,包括你的代码中定义的方法和包含的库文件。下面的策略可以帮你避免触碰到dex文件限制。

  • 查看应用直接和传递的依赖。确保你添加的任何大的依赖库在添加时要好过把所有代码加进去的总和。一个常见的反例就是包括一个大的依赖库,但是只有一小部分的工具类方法是有用的。减少你的应用代码依赖可以帮助你避免dex限制。
  • 使用ProGuard移除未使用的代码,为你的应用配置ProGuard设置,然后运行ProGuard,确保混淆适用于开放版本。使用混淆确保你没有把未使用的代码放入apk中。

使用这些技巧可以帮你避免构建配置时需要更多的方法。这些方法同样可以减少apk的体积,对于推广成本大的市场是很重要的。

通过Gradle配置多dex

在Android SDK Build Tools 21.1及更高版本中的Android的Gradle插件在构建配置中支持多dex。确保你更新了Android SDK Build Tools和Android Support Repository 是最新版本。
设置你的应用项目使用多dex需要你对项目做一些修改。你需要做以下几步:

  • 改变Gradle构建来支持多dex
  • 修改Manifest,依赖 MultiDexApplication类

修改build.gradle 来包括依赖库,使用多dex输出,如以下截图:

android {
    compileSdkVersion 21
    buildToolsVersion "21.1.0"

    defaultConfig {
        ...
        minSdkVersion 14
        targetSdkVersion 21
        ...

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

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

在manifest里面从多dex依赖包中添加MultiDexApplication到应用元素中。

<?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>

当这些配置信息添加到应用中,Android build tools构建一个主dex(classes.dex)和支持dex(classes2.dex,classes3.dex)。构建系统最后发布时会把这些打包到apk文件中

Note: If your app uses extends the Application class, you can override the attachBaseContext() method and call MultiDex.install(this) to enable multidex. For more information, see the MultiDexApplication reference documentation.

多dex依赖库的限制

多dex依赖库有一些常见的限制,当你将他们纳入你的应用构建系统时应该知晓这些。

  • 在启动过程中dex文件安装到设备数据上是很复杂的,如果二级dex文件非常大会导致ANR。在这种情况下,你应该使用Proguard的缩包技巧来缩小dex文件的体积,移除未使用的代码。
  • 由于Dalvik linearAlloc的bug,使用多dex的应用可能不会在Android4.0以前的设备启动。如果你的目标是14以前的,确保在那些启动或者加载特定的部分类中出现问题的版本上做好测试。压缩代码可以减少或者消除这些潜在的问题。
  • 由于Dalvik linearAlloc的bug,使用了多dex配置的应用汇占据很大的内存,在运行时容易崩溃。这个占用限制在Android4.0(API 14)增大了,但是应用仍然容易在Android5.0(API 21)以前的Android版本到达这个限制。
  • 考虑到运行时在主dex文件中需要哪些类会有很多复杂的需求。Android构建工具控制Android的需求,但是很有可能其他包含了依赖包的又有额外的依赖需求包括自己检查和native代码的调用。有些依赖库无法使用,只有多dex构建工具更新到允许你指定那些需要包括入主dex的类。

优化多dex构建

一个多dex配置需要明显增加的构建时间,因为构建系统需要做很复杂的判断,决定哪些类必须进入主dex文件,哪些类可以进入二级dex文件。这个意味着路线构建占据了一部分的发展过程,多dex明显的变长,很有可能减慢发展过程。
为了减缓构建输出过程的时间变长,通过使用productFlavors创建两个构建输出,一个开发输出,一个产品输出。
对于开发输出,设置最小的SDK版本是21。这个设置在ART的格式下产生多dex文件更快。对于产品输出,设置最小的sdk版本来匹配实际需要的版本。这种设置可以生成适配更多设备的多dex的apk文件,但是花费更多的时间去创建。
以下的构建配置例子演示了如何在Gradle文件中设置这些输出:

android {
    productFlavors {
        // Define separate dev and prod product flavors.
        dev {
            // dev utilizes minSDKVersion = 21 to allow the Android gradle plugin
            // to pre-dex each module and produce an APK that can be tested on
            // Android Lollipop without time consuming dex merging processes.
            minSdkVersion 21
        }
        prod {
            // The actual minSdkVersion for the application.
            minSdkVersion 14
        }
    }
          ...
    buildTypes {
        release {
            runProguard true
            proguardFiles getDefaultProguardFile('proguard-android.txt'),
                                                 'proguard-rules.pro'
        }
    }
}
dependencies {
  compile 'com.android.support:multidex:1.0.0'
}

当你完成这些配置更改之后,你可以使用devDebug 变量,这个结合了dev和debug的属性。使用这个创建一个proguard失效、多dex生效、最小版本21的debug应用,这些配置导致Gradle作如下事情:

  1. 构建应用中每一个模块作为独立的dex文件。这个称作预dex
  2. 将每个dex文件包入apk中,不做更改
  3. 最重要的是,这些dex文件不会被结合,所以这些花费长时间计算那些属于主dex的内容的过程会避免。

这些配置导致快速的增加构建,因为只有那些修改过的模块的dex文件会重新计算重新打包进apk中。由这些构建产生的apk文件只能在Android5.0以上的设备上测试。然而,由于执行这些配置作为一个输出,你保留了执行包括发布版本和proguard设置的正常构建的能力。
你也能构建其他变量,包括prodDebug 变量构建,花费更长的构建时间,但是可以用于开发测试之外的。prodRelease 变量是最后的测试和发布版本。如果你通过命令行来执行Gradle命令,你可以使用DevDebug来执行,如./gradlew installDevDebug 更多的构建任务,可以去看Gradle构建指导。

Tip: You can also provide a custom manifest, or a custom application class for each flavor, allowing you to use the support library MultiDexApplication class, or calling MultiDex.install() only for the variants that need it.

在Android Studio中使用构建变量

构建变量在管理使用多dex的构建过程非常有用。Android Studio 允许你在UI中选择构建变量。
在你的app中使用devDebug构建变量:

  1. 从左侧打开构建变量窗口,选项在最喜欢的下面。
  2. 点击构建变量,选择一个不同的变量

Note: The option to open this window is only available after you have successfully synchronized Android Studio with your Gradle build file using the Tools > Android > Sync Project with Gradle Files command.

测试多dex应用

当使用设备测试多dex应用时,额外的配置需要激活。因为类中代码的位置不是在一个独立的dex文件中,设备测试不会允许的很准确除非配置了多dex。
测试多dex应用,从多dex支持库中配置MultiDexTestRunner 。如下的build.gradle 演示了如何配置参数。

android {
  defaultConfig {
      ...
      testInstrumentationRunner "com.android.test.runner.MultiDexTestRunner"
  }
}

Note: With Android Plugin for Gradle versions lower than 1.1, you need to add the following dependency for multidex-instrumentation:

dependencies {
    androidTestCompile('com.android.support:multidex-instrumentation:1.0.1') {
         exclude group: 'com.android.support', module: 'multidex'
    }
}

你可以使用设备测试来直接或者扩展来适应你的测试用例。可选择的,你可以复写onCreate 如下:

public void onCreate(Bundle arguments) {
    MultiDex.install(getTargetContext());
    super.onCreate(arguments);
    ...
}

Note: Use of multidex for creating a test APK is not currently supported.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值