如果移动端访问不佳,请访问 –> 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 21    buildToolsVersion "21.1.0"    defaultConfig {        ...        minSdkVersion 14        targetSdkVersion 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 file            w.append('\n')            new File("${projectDir}/multidex.keep").withReader { r ->                // And write data from the input into the output                w << 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            // optional            dx.additionalParameters += "--main-dex-list=$projectDir/class-list.txt".toString() // enable the main-dex-list            dx.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.张

更多相关文章

  1. 低版本android project在高版本ADK中运行方法
  2. android创建隐藏文件或者文件夹,并对其读写操作
  3. Android项目--团购类客户端
  4. Android中应用界面主题Theme使用方法和页面定时跳转应用
  5. [基础知识]全面认识AndroidManifest.xml文件(二)
  6. G1安装android软件方法 (实机运行)
  7. android设置主题和自定义主题的方法
  8. android下修改hosts文件不起作用(无效)的解决办法
  9. android 模拟器手机如何添加文件到sd卡

随机推荐

  1. Android DEX 方法超过64K限制
  2. android--创建快捷方式和判断是否已经创
  3. Android ApiDemos示例解析(137):Views->L
  4. 高煥堂的四本Android开发新書(簡體完整版
  5. Android的内存优化相关记录
  6. ubuntu9.10安装android SDK
  7. Android中垃圾回收日志信息
  8. android获取手机型号和系统版本号
  9. 【Android】Android处理Home键方法小结
  10. Android常用方法——获取系统信息