我们都知道安卓的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 21buildToolsVersion '21.1.2'defaultConfig {applicationId "com.lifesense.happyrun"minSdkVersion 18targetSdkVersion 21versionCode 1versionName "1.0.28"multiDexEnabled true}}dependencies {compile 'com.android.support:multidex:1.0.1'}

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

  1. 修改minifest文件,name为MultiDexApplication

        <applicationandroid: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 { @Overrideprotected 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 trueproguardFiles 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

精简我们的apk的方法相关推荐

  1. android系统精简掉music.apk后设置铃声的方法

    2012-09-10 更新: 今天无意中发觉,"360优化大师",里面也可以 设置 来电铃声 和 短信铃声 由于这个 软件设置 真的很简单,就不截图了: 打开优化大师-->向 ...

  2. 酷派8150S(移动定制版)可用的第三方Recovery备份数据、刷机并精简系统内置APK经验...

    希望使用的第三方Recovery下载地址: ClockworkMod ROM Manager - Recoveries http://clockworkmod.com/rommanager 适配的型号 ...

  3. hbuildx打包成apk_HBuilder打包webapp为apk的方法

    本文主要为大家带来一篇利用HBuilder打包前端开发webapp为apk的方法.小编觉得挺不错的,现在就分享给大家,也给大家做个参考.一起跟随小编过来看看吧,希望能帮助到大家. 现在的前端开发可谓是 ...

  4. as将安卓应用打包_Android Studio打包生成apk的方法(超级简单哦)

    释放双眼,带上耳机,听听看~! 打包文件是需要生成APK文件,其他人可以通过APK安装和使用,一般来说,包是指APK生成的发布版本,下文技术狗小编还介绍了Android Studio 超级简单的打包生 ...

  5. mcldownload文件夹_《我的世界》中国版游戏空间精简教程 多余文件删除方法

    <我的世界>中国版游戏空间精简教程 多余文件删除方法 2017-09-05 16:09:32来源:网易论坛编辑:评论(0) <我的世界>中国版自从更新后很多玩家都反映游戏所需空 ...

  6. Eclipse build Android时不生成apk问题解决方法

    Eclipse build Android时不生成apk问题解决方法 参考文章: (1)Eclipse build Android时不生成apk问题解决方法 (2)https://www.cnblog ...

  7. 安卓java安装apk代码_Android 通过代码安装 APK的方法详解

    在 APK 开发中,通过 Java 代码来打开系统的安装程序以安装 APK 并不是什么难事,一般的 Android 系统都有开放这一功能. 但随着 Android系统版本的迭代,其对于权限的把控越来越 ...

  8. php网站怎么打包成apk,Android编程实现webview将网页打包成apk的方法

    本文实例讲述了Android编程实现webview将网页打包成apk的方法.分享给大家供大家参考,具体如下: 功能非常简单,而且乍一看没什么特别大的用处,因为实际上就是浏览器而已...但如果说网页一开 ...

  9. Unity Android 之 在 Unity 中直接调用打开其他应用apk的方法实现

    Unity Android 之 在 Unity 中直接调用打开其他应用apk的方法实现 目录 Unity Android 之 在 Unity 中直接调用打开其他应用apk的方法实现 一.简单介绍 二. ...

最新文章

  1. 微信小程序之录音与播放功能(完整示例demo)
  2. 恢复错误:\anaconda3\lib\site-packages\zmq\backend\cffi\__pycache__\_cffi_ext.c(266)
  3. Big-Endian和Little-Endian
  4. docker 二进制安装
  5. Hadoop 2.x 完全分布式HA集群环境搭建
  6. 【数据竞赛】ICCV 2021 竞赛汇总
  7. 前端预览word文件_2020国开形考计算机练习题Word练习
  8. Scrum之 Sprint计划会议
  9. 图像风格迁移cvpr2020_CVPR 2020 | 浙大李俊成:用无监督强化学习方法来获得迁移能力...
  10. electron 桌面程序_如何使用Electron使用JavaScript构建您的第一个桌面应用程序
  11. BZOJ4868: [Shoi2017]期末考试
  12. C# const与readonly的用法和区别解析(转)
  13. Hadoop序列化及案例
  14. T-SQL语句实现数据库备份与还原功能
  15. python二次开发ug_CAD二次开发(UG/Proe/其他) - 随笔分类 - 白途思 - 博客园
  16. Git 基础命令与事件详解(基础版)
  17. Ubuntu的shell脚本踩keng-unexpected operator
  18. K210入门,用wifi通讯
  19. C++作业5 求和 、数组选择
  20. JAVA 面试(更新)

热门文章

  1. 黑马程序员--Java学习10--访问权限
  2. DeepSurf: A surface-based deep learning approach for theprediction of ligand binding sites on prote
  3. 【Python+C#】手把手搭建基于Hugging Face模型的离线翻译系统(如果你想,也可以在线)
  4. 【c#系列】PDF进行操作-浏览、分割、合并、插入、删除(1)
  5. java cos和native cos的区别
  6. 图纸上标注的是实际尺寸吗_CAD或工程图上与实际尺寸比例公式有?
  7. 12306系统架构优化
  8. java编程思想读书笔记
  9. 如何阅读matlab项目并调试运行成,【转】读书笔记:MATLAB
  10. Field error in object ‘xxx‘ on field ‘xxx‘: rejected value [xxx]