精简我们的apk的方法

这篇博客探讨了如何应对Android应用程序超过65K方法限制的问题。首先介绍了简单暴力的优化方法,如删除不必要的库和合并代码。接着详细讨论了Multidex方案,包括其配置、潜在缺陷和优化建议。此外,还提到了插件化作为更复杂的解决方案,以及它在大型项目中的应用和动态加载技术的重要性。最后,提供了相关测试问题和参考资料。

我们都知道安卓的65K方法坑。

com.android.dex.DexIndexOverflowException: method ID not in [0, 0xffff]: 65536
at com.android.dx.merge.DexMerger$6.updateIndex(DexMerger.java:484)
at com.android.dx.merge.DexMerger$IdMerger.mergeSorted(DexMerger.java:261)
at com.android.dx.merge.DexMerger.mergeMethodIds(DexMerger.java:473)
at com.android.dx.merge.DexMerger.mergeDexes(DexMerger.java:161)
at com.android.dx.merge.DexMerger.merge(DexMerger.java:188)
at com.android.dx.command.dexer.Main.mergeLibraryDexBuffers(Main.java:504)
at com.android.dx.command.dexer.Main.runMonoDex(Main.java:334)
at com.android.dx.command.dexer.Main.run(Main.java:277)
at com.android.dx.command.dexer.Main.main(Main.java:245)
at com.android.dx.command.Main.main(Main.java:106)

最近搞的项目也是轻松超越,哎,现在的项目越来越大,功能越来越多,还没怎么用,要求一次上齐那么多功能也是挺奇葩的,加班也越来越多,无限的不理解,有点做得很没意思啊。。

解决方案:

1. 简单暴力版

删除没要so库,合并一些方法,去掉代码中没使用到的函数,去掉没有使用到的jar包,以及将类中成员由private换成public,减少set/get函数。
虽然这些都是治标不治本的方法
不过对于在这个边界65K左右的情况确实很好的一个方法!!
这里有一个包,用来帮助你查看各个package里面的方法数的,
这样你就可以根据这个做一个参考,替换更小的包等。

java -jar path\dex-method-counts.jar path\App.apk

这里写图片描述

2. multidex

谷歌在2014年就提出这个解决方案,这个还是很简单实惠的!
在我们的build.gradle 文件里面加多multiDexEnabled true,同时加多multidex包!

    android {
        compileSdkVersion 21
        buildToolsVersion '21.1.2'
        defaultConfig {
            applicationId "com.lifesense.happyrun"
            minSdkVersion 18
            targetSdkVersion 21
            versionCode 1
            versionName "1.0.28"

            multiDexEnabled true
        }
    }

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

配置好后,我们需要做的就是修改我们application类。
三种方案:

  1. 修改minifest文件,name为MultiDexApplication

        <application
            android:name="android.support.multidex.MultiDexApplication"
            android:allowBackup="true"
            android:icon="@mipmap/icon_app"
    
  2. 修改我们的application继承于MultiDexApplication

          public class MyApp extend MultiDexApplication{
    
            } 
    
  3. 修改我们的app的一个函数。

         public class MyApplication extends Application { 
    
                @Override
                protected void attachBaseContext(Context base) {
                    super.attachBaseContext(base);
                    MultiDex.install(this);
                }
        }
    

好了,总共就这样,我们的apk如果超过65k方法,就会被压成两个dex文件。

MultiDex缺陷

但这方案还是有缺陷的,你需要测试下这个压缩包是否还有效!

  • ANR
    应用MultiDex后,这个程序在安装和开启过程会相对复杂,从而导致ANR问题,如果第二个dex文件比较大的话,在这种情况,你需要使用ProGurad来尽可能的减小dex的大小和移出些没用的代码!
  • 安卓4.0无法启动
    对于运行旧于4.0的系统,因为一个Dalvik linearAlloc的缺陷,会有可能无法启动。如果你要去支持这部分旧版系统,需要自己测试下,因为在特定累的加载过程都有可能导致bug。
  • 内存消耗问题
    采用multidex方案的会有更大的内存消耗从而导致程序崩溃,因为有这么一个Dalvik linearAlloc 限制的bug–78035,这个bug虽然在4.0被调整了。

优化建议

在生产的过程会相对的耗费大量的时间的,因为系统要做很多的决定和判断那些文件放到第一个dex,那些放到第二个DEX里面去。为了缩短build的时间,建议弄两个flavor,一个是开发测试环境,一个是生产环境的。开发环境设最小SDK为21,因为会使用ART技术来加快生产。对于生产环境就设置实际的

android {
    productFlavors {         
        dev {
             minSdkVersion 21
        }
        prod {             
            minSdkVersion 14
        }
    }
      ...
    buildTypes {
        release {
            runProguard true
            proguardFiles getDefaultProguardFile('proguard-android.txt'),
                                                 'proguard-rules.pro'
        }
    }
}

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

测试问题

这带来的另外一个问题也是测试问题,当我们用instrumentation 来测试时候,需要多额外的配置,具体如下

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

如果你的gradle是低于1.1的(话说现在都出到2.0了,还用1.1也太旧了),还需要下面这个:

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);
    ...
}

3. 插件化

插件化是一个现对来说很重的一个解决方案,需要修改的地方很多。
具体参考美团的帖子
美团Android DEX自动拆包及动态加载简介

另外提一点的是,很多大型的为了多团队的合作,快速的集成,交付等,实用的就是“插件化开发”,
你去看下微信的包,就各种库,各种插件。
因为需要减轻应用太大时候带来的内存和cpu占用问题。你看每次打开微信那卡的。简直。。。。。。
人家已经维持优化了很多还是这样,可见。安卓手机实在不给力啊。。。。

关于动态加载技术,网上有很多文章,刚兴趣的可以自己看下。


参考资料
谷歌的官方解释:Building Apps with Over 65K Methods

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值