我们都知道安卓的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类。
三种方案:
修改minifest文件,name为
MultiDexApplication<application android:name="android.support.multidex.MultiDexApplication" android:allowBackup="true" android:icon="@mipmap/icon_app"修改我们的application继承于
MultiDexApplicationpublic class MyApp extend MultiDexApplication{ }修改我们的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
这篇博客探讨了如何应对Android应用程序超过65K方法限制的问题。首先介绍了简单暴力的优化方法,如删除不必要的库和合并代码。接着详细讨论了Multidex方案,包括其配置、潜在缺陷和优化建议。此外,还提到了插件化作为更复杂的解决方案,以及它在大型项目中的应用和动态加载技术的重要性。最后,提供了相关测试问题和参考资料。

577

被折叠的 条评论
为什么被折叠?



