如果移动端访问不佳,请访问 –> Github版

背景

Android 的 classLoader 在加载 APK 的时候限制了class.dex 包含的 Java 方法数,其总数不能超过65535(64K,不要再说成 65K 了,1K = 2^10 = 1024 , 64 * 1024 = 65535),Google 官方给出的解决方案是使用 Multidex 。

启用 Multidex

基本要求:

  • 使用 Android Studio 开发工具
  • Android SDK Build Tools >= 21.1
  • 更新 Android Support Repository 到最新版本

配置步骤:

  1. 配置 Gradle build 来开启 multidex
  2. 修改 manifest 来引用 MultiDexApplication 类

修改 module 下的 build.gradle 文件,添加支持库并开启 multidex:

android {compileSdkVersion 21buildToolsVersion "21.1.0"defaultConfig {...minSdkVersion 14targetSdkVersion 21...// Enabling multidex support.multiDexEnabled true}...
}dependencies {compile 'com.android.support:multidex:1.0.0'
}

PS: compileSdkVersion、buildToolsVersion 根据实际项目配置,但是版本不能低于上述版本。

AndroidManifest.xml 中给 application 节点添加对 MultiDexApplication 类的引用:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="xxx"><application
        ...android:name="android.support.multidex.MultiDexApplication">...</application>
</manifest>

PS: manifest 节点的 package 属性值根据实际项目有所不同。

注意:如果你的 APP 使用了继承 Application 的类,你需要重写attachBaseContext()方法并调用 MultiDex.install(this) 来启用 multidex 。

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

网上搜到还有一个方法:不继承 Application ,而是直接继承 MultiDexApplication 即可,这样就不需要重写attachBaseContext()方法了。

参考资料:Configure Apps with Over 64K Methods

可能遇到的问题

NoClassDefFoundError

Android SDK Build Tools 21.1 或者更高版本中的 Gradle Android 插件有对 multidex 的支持。这个插件使用 Proguard 来分析你的项目并在 [buildDir]/intermediates/multi-dex/[buildType]/maindexlist.txt 文件中生成一个 app 启动 classes 的列表。但是这个列表并不是100%准确,可能会丢失一些app启动所需的 classes 。

如果你在本地的测试机上没有遇到这个问题,并不代表你的 APP 没有问题,我通过查看友盟的崩溃记录和使用一些真机测试平台来进行检查,通常情况下会有所发现。

解决方法:在 module 下创建 multidex.keep 文件,并在其中罗列出那些 class,以便让编译器知道在 main dex 文件中要保持哪些 class。

生成 multidex.keep 文件中的内容有多种:

方法一:修改 module 下的 build.gradle 文件

apply plugin: 'com.android.application'
android {...
}
dependencies {...
}
android.applicationVariants.all { variant ->task "fix${variant.name.capitalize()}MainDexClassList" << {logger.info "Fixing main dex keep file for $variant.name"File keepFile = new File("$buildDir/intermediates/multi-dex/$variant.buildType.name/maindexlist.txt")keepFile.withWriterAppend { w ->// Get a reader for the input filew.append('\n')new File("${projectDir}/multidex.keep").withReader { r ->// And write data from the input into the outputw << r << '\n'}logger.info "Updated main dex keep file for ${keepFile.getAbsolutePath()}\n$keepFile.text"}}
}
tasks.whenTaskAdded { task ->android.applicationVariants.all { variant ->if (task.name == "create${variant.name.capitalize()}MainDexClassList") {task.finalizedBy "fix${variant.name.capitalize()}MainDexClassList"}}
}

方法二:修改 module 下的 build.gradle 文件

apply plugin: 'com.android.application'
android {...afterEvaluate {tasks.matching {it.name.startsWith('dex')}.each { dx ->if (dx.additionalParameters == null) {dx.additionalParameters = []}dx.additionalParameters += '--multi-dex' // enable multidex// optionaldx.additionalParameters += "--main-dex-list=$projectDir/class-list.txt".toString() // enable the main-dex-listdx.additionalParameters += '--minimal-main-dex'}}
}
dependencies {...
}

使用上述任意方式配置完成后,clean 然后 rebuild 项目,完成之后在 module 下的build/intermediates/multi-dex/xxx里找到 maindexlist.txt 文件(如果找不到相关目录,可能需要你同步后 rebuild 项目才能生成),复制里面的内容到 module 根目录下 multidex.keep 文件中(没有则先创建此文件)。

然后,比较重要的一步就是:通过友盟、测试记录、Bug记录等获取到 NoClassDefFoundError 错误对应的类,按照 maindexlist.txt 文件的方式添加这些类到 multidex.keep 文件中就可解决了。

其他错误和问题

比如首次安装启动时黑屏没有响应/ANR安装时异常等,你可以参考文末的一些文章,此外你还可以参考 Android 必知必会-Android Splash 页秒开之细节处理 来优化启动体验。

参考资料和推荐阅读:

  • Android Multidex 遇到的问题 (推荐此文)
  • Android的multidex带来的性能问题-减慢app启动速度
  • ClassNotFoundException

总结

这是一篇早就准备写的文章,但当时搜集的资料未及时保存或者丢失,就拖到了现在。因为一个比较旧的 APP 也遇到了相关的问题,所以重新搜集了下资料整理发布出来了,希望能帮到遇到相关问题的朋友们。

PS:你可以通过下面的方式和我联系

  • 微博:cafeting
  • Github: likfe
  • CSDN:他叫自己Mr.张

Android 项目开发填坑记 - 使用 MultiDex 解决 64K 限制相关推荐

  1. Android项目开发填坑记-Fragment的onAttach

    背景 现在Android开发多使用一个Activity管理多个Fragment进行开发,不免需要两者相互传递数据,一般是给Fragment添加回调接口,让Activity继承并实现. 回调接口一般都写 ...

  2. Android 项目开发填坑记 - 谷歌商店上架被拒 Apps On Device

    关键词:谷歌商店被拒.数据安全表单.已安装应用.Policy Declaration.Data Safety Section.App Activity Data Type.Apps On Device ...

  3. Java web 开发填坑记 2 -如何正确的创建一个Java Web 项目

    转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/72566261 本文出自[赵彦军的博客] Java web 开发填坑记 1-如何正确 ...

  4. 支付开发填坑记之支付宝

    支付宝在所有支付方式中最好开发的了,因为文档比较清晰,而且开发起来也比较简单.因此,支付宝的坑是相对较少的. 原文地址 APP支付 APP支付步骤为: 获取支付宝的配置信息. 生成商家订单信息. 根据 ...

  5. php项目简介,一、项目简介 · ThinkPHP5项目开发“填坑”实录 · 看云

    ###项目简介 [TOC=4,6] 所有的关于技术细节的讨论和实现都是基于一定的项目背景的,所以首先来介绍下我做的项目情况.这里要介绍的项目是一个**作业管理系统**.对你没看错,就是一个简单的学生交 ...

  6. 小程序项目之填坑小记

    作者:首席填坑官∙苏南 公众号:honeyBadger8,本文原创,著作权归作者所有,转载请注明原链接及出处. 简诉 是的,真的,你没有看错,我就是上次那个加薪的,但是现在问题来了,最近又搞了个小程序 ...

  7. 为微信开发填坑:微信网页支付的开发流程及填坑技巧 1

    GitChat 作者:极笔北客 原文:为微信开发填坑:微信网页支付的开发流程及填坑技巧 关注微信公众号:「GitChat 技术杂谈」 一本正经的讲技术 [不要错过文末彩蛋] 小程序作为微信之父张小龙钦 ...

  8. 为微信开发填坑:微信网页支付的开发流程及填坑技巧

    GitChat 作者:极笔北客 原文:为微信开发填坑:微信网页支付的开发流程及填坑技巧 关注微信公众号:「GitChat 技术杂谈」 一本正经的讲技术 [不要错过文末彩蛋] 小程序作为微信之父张小龙钦 ...

  9. Android项目开发—GeoQuiz

    Android项目开发-GeoQuiz 应用规划 确定功能 必须的界面及界面跳转的流程 ... 界面设计 主界面确定 模块界面.列表.查看.编辑界面 添加需要的组件 ... 数据操作和存储 业务实现 ...

最新文章

  1. GridView分页(第一页、上一页、下一页、最后页、当前页数/总页数)
  2. openssl aes加解密的使用
  3. PHP-FPM对比Swoole:Swoole多了Reactor线程监听Socket 句柄的变化 代码初始化一次不结束进程 ws tcp mqtt服务
  4. React学习:入门实例-学习笔记
  5. 阿基米德椭圆规原理,你看懂了吗?
  6. 正向代理、反向代理和透明代理的详解
  7. “ORA-00932: 数据类型不一致: 应为 -, 但却获得 CLOB “一种情况的解决
  8. 2016.8.26 动态规划及杂题选讲 [树形dp] [数论] [矩阵快速幂]
  9. 使用java抓取金山词霸的每日一句
  10. 加字邮票价格_中华人民共和国邮票(加字改值邮票)
  11. NetworkX学习笔记07:泊松分布与幂律分布
  12. 老师傅传授,数控车床对刀步骤
  13. 你会copying了吗?(Effective C++ 12 复制对象时勿忘其每一个成分)
  14. 完蛋!面试官问我 InnoDB 的物理存储结构!
  15. 苹果选了天猫 天猫成了618
  16. 英语专业有计算机课程吗,英语专业转行学计算机能学好吗
  17. kettle中的switch_kettle 条件判断 Switch Case
  18. Python量化代码源码160个,聚宽直接使用,已全部整理
  19. STM32项目设计:基于STM32指纹密码锁
  20. AAAI2020/风格迁移:Ultrafast Photorealistic Style Transfer via Neural Architecture基于神经结构搜索的超快逼真风格转移

热门文章

  1. Glade的简单使用说明+例子(一)
  2. 使用 nginx 做加速
  3. Microsoft.Practices.Unity实现代码依赖注入、XML依赖注入和AOP切面编程
  4. 九大行星 神话 英文
  5. Nginx实战学习之负载均衡
  6. native react 图片多选_react-native实现的多图片选择器
  7. 中国计算机科学实验室,上海交通大学计算机科学与工程系(CSE)
  8. 多处理机Cache一致性问题及解决办法
  9. mysql数据库所有版本安装包下载地址
  10. echarts实现西安地铁图