• 热门专题

AndroidDeveloper:构建超过65K方法的App

作者:  发布日期:2016-01-08 19:50:47
Tag标签:方法  
  • Android App的大小随着Android平台持续增长。当你的应用程序和它引用的库达到某个大小,你会遇见预示你的App已经达到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。这个数字有重要意义,它代表了在一个单独的Dalvik Executable字节文件中可以被调用代码的总数。如果你构建一个Android应用并且发生了这个错误,那么恭喜你,你有许多的代码!这个文档讲解了如何摆脱这个限制继续构建你的应用。

     

    注意:本文档提供的指导取代了在Android开发者博客中发布的Custom Class Loading in Dalvik指导。

     

    大约65千引用限制

    —————————————————————————————————————————

    Android应用文件(APK)包以含Davik Executable形式(DEX)的可执行字节码文件,它包含了用于你应用执行的编译代码。Davik Executable规范限制在一个DEX文件中可以被调用的方法的总数为65536,包含Android framework方法,库方法,和你自己的代码方法。为了打破这个限制要求,你可以配置你的应用构建进程生成多个DEX文件,被称为multidex配置。

    Android5.0之前的Mutidex支持

    Android5.0之前的平台版本使用Dalvik运行时执行应用代码。默认,Dalvik限制应每个APK只有一个classes.dex字节码文件。为了绕过这个限制,你可以使用multidex support library,它开始启动你的应用的主要DEX文件,然后控制访问额外的DEX文件和它们的代码;

    Android5.0和更高的Mutidex支持

    Android5.0和更高使用一个称为ART的运行时,它天然的支持应用APK文件多个dex文件。ART在应用安装时执行预编译,它扫描classes(…N).dex文件并且将它们编译成一个.oat文件在Android设备上执行。更多关于Android5.0运行时的信息,请查阅introducing ART。

     

    避免65K限制

    —————————————————————————————————————————

    在配置你的应用程序启动使用超过65K方法引用之前,你应该采取措施来减少你的应用代码调用引用的总数,

    包含你的应用代码或者包含库的方法定义。下面的策略能帮助你避免突破dex引用限制:

    • 检查你的应用的直接和传递依赖-确保在你的应用中你包含的任何大的库依赖以某种方式被使用,那么被添加到应用程序中的代码数量偏大。相反面就是由于很少的实体方法是有用的而包含一个非常大的库。减少你的应用代码依赖通常能帮助你避免dex引用限制。

    • 使用ProGuard移除没有使用的代码-为你的应用配置ProGuard设置运行ProGuard,并且确保你为release构建启动了压缩。启动压缩确保你没有在你的APK中装载没有使用的代码。

       

      使用这些技术能帮助你在你的应用中避免为了启动更多的方法引用,而要求的配置改变。这些不能也能减少你的APK的大小,它对带宽成本特别高的市场来说特别重要。

       

      在Gradle中配置你的应用支持Multidex

      —————————————————————————————————————————

      在Android SDK Build Tools 21.1和更高提供的Android Gradle插件,支持multidex作为你的构建配置的一部分。在为你的应用尝试配置multidex之前,确保你更新了Android SDK Build Tools并且Android Support Repository是最新的版本。

       

      设置你的应用程序开发项目使用multidex配置指需要你的应用开发项目做很小的改动。你需要执行下面的步骤:

      • 改变你的Gradle构建配置来启动multidex

      • 修改你的清单文件引用MultiDexApplication类

         

        就像下面Gradle构建文件代码段中展示的,修改你的应用的Gradle构建文件配置来包含支持库并且启动multidex输出。

         

        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' 
        } 
        注意:你可以在你的Gradle配置文件中的defaultConfig,buildType,或者productFlavor部分指定multiDexEnabled设置。

         

         

        在你的清单文件中添加MultiDexApplication类,从multidex支持库添加到你的应用程序元素。

         

        <?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构建工具根据需要创建一个主要的dex(classes.dex)和支持(classes2.dex,classes3.dex)。构建系统然后将会将他们打包到一个APK文件中用于发布;

         

        注意:如果你的应用使用继承Application类,你可以覆盖attachBaseContext()方法和调用MultiDex.install(this)来启动multidex。更多的信息,请查阅MultiDexApplication参考文档。

         

        multidex支持库的局限

        —————————————————————————————————————————

        multidex支持库有一些总所周知的局限,那么当你向你的应用构建配置中引入它的时候应该关注并测试它:

        • 在启动到一台设备的数据分组时,.dex文件的安装是复杂的,并且如果第二个dex文件非常大,可能导致应用程序无法响应(ANR)错误。在这种情况下,你应该使用ProGuard代码缩减技术来减少dex文件的大小,并且移除未使用部分的代码。

        • 使用multidex的应用程序可能在比Android4.0(API Level 14)更早的

          … …

          优化Multidex开发构建

          —————————————————————————————————————————

          multidex配导致构建处理的时间显着的增加,因为构建系统必须做出复杂的决策,关于什么类必须被包含在最初的Dex文件中,和什么类能被包含在第二个Dex文件。这就意味着使用multidex的日常构建,作为开发过程的一部分被执行的更长,并且会减缓你的开发进程。

           

          为了multidex输出减轻更长的构建时间,你应该使用Android Gradle插件productFlavors:在你的构建输出上创建两个变量:一个开发Flavor和一个生产flavor。

           

          对于开发Flavor,设置最小的SDK版本为21。这个设置使用支持ART格式生成multidex输出更快。对于生成Flavor,设置最低的SDK版本和你实际支持的最小级别一样。这个设置生成一个兼容更多设备的multidex APK,但是花费更长时间来构建。

           

          下面的构建配置例子演示了如何在Gradle构建文件中设置这些Flavor:

           

          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生产Flavor属性和debug构建类型。使用这个不启用proguard,支持multidex,并且最先的SDK版本设置为Android API level 21的目标创建一个debug应用。这些设置使得Android gradle插件执行如下工作:
          1. 构建应用程序的每个模块(包含依赖)作为单独的dex文件。这通常被称为pre-dexing。

          2. 在API中包含未修改的每个dex文件。

          3. 最重要的是,module dex文件不会被结合,和决定最初的dex文件内容的大量时间被避免。

             

            这些设置使得快速、增量构建,因为仅仅被修改模块的dex文件被重新计算,并且打包到APK文件中。这些设置产生的APK仅仅能被用在Android5.0设备上测试。然而,通过实现了flavor形式的设置,你保留了在合适的生产最新SDK级别和proguard设置执行正常构建的能力。

             

            你也能构建其它的实体,包含一个proDebug实体构建,他花费更长的时间,但是能被用于测试以外的开发。

            … …

             

            在Android Studio中使用构建实体

            构建实体对于管理构建进程什么时候使用multidex非常有用。Android允许你在用户界面选择这些构建实体。

             

            为了让Android Studio构建你的应用的"devDebug"实体:

            1. 在左侧栏中打开Build实体窗口,选项位于Favorites旁边。

            2. 点击构建实体的名字来选择不同的实体,如图1所示。

              注意:打开窗口中的选项仅仅在你使用Tools>Android>Sync Project with Gradle Files命令,使用你的Gradle构建文件成功同步Android Studio之后才有效。

               

              测试Multidex应用

              —————————————————————————————————————————

              测试使用了multidex配置的应用需要一些额外的步骤和配置。因为类的代码位置没有在一个单独的DEX文件中,instrumentation测试无法正常运行,除非配置支持multidex。

              当测使用instrumentation测试一个multidex应用的时候,使用来自multidex测试支持库中的MultiDexTestRunner。下面的build.gradle文件例子,演示了如何配置你的构架使用这个test runner:

               

              android { 
              ? defaultConfig { 
              ? ? ? ... 
              ? ? ? testInstrumentationRunner "android.support.multidex.MultiDexTestRunner" 
              ? } 
              } 
               
              dependencies { 
              ? ? androidTestCompile 'com.android.support:multidex-instrumentation:1.0.0' 
              } 
              你可能直接或者继承使用instrumentation测试runner类,来满足你的测试需要。或者你可以像在存在的instrumentations中这样覆盖onCreate:

               

              public void onCreate(Bundle arguments) { 
              ? ? MultiDex.install(getTargetContext()); 
              ? ? super.onCreate(arguments); 
              ? ? ... 
              } 
              注意:使用multidex创建一个测试APK现在不被支持。

               

About IT165 - 广告服务 - 隐私声明 - 版权申明 - 免责条款 - 网站地图 - 网友投稿 - 联系方式
本站内容来自于互联网,仅供用于网络技术学习,学习中请遵循相关法律法规