参考资料:http://www.infoq.com/cn/news/2014/11/android-multidex
在一个老项目上,增加了一个新模块。用的测试机一直都是5.0的,所以都能正常运行。临近上线的时候,在4.4的手机上竟然打开就闪退了,看了下log,java.lang.NoClassDefFoundError……,Could not find class……,直接定位到
private Handler handler = new Handler() {}这一行。但是不应该啊,这个内部类明明存在的啊,为什么会找不到,
而且在5.0版本上也是能正常运行的。这也只是一个Handler,不可能只是5.0的新特性而5.0以下版本不具有。
这时候就想到了是不是我添加的新模块引入的库与以前项目中的库有冲突,所以导致NoClassDefFoundError。于是我
就把新加入的模块删了,可以运行,所以使我更加确信是库冲突的原因。于是就开始陷入了这个误区里面。通过不断的删除
新引入的库和更改库的版本,新加入的类也是逐渐加进去,方便看出冲突原因,这持续了一周时间。到最后,当我认为
将要解决这个的问题的时候,还有三个类,一放到项目中就还是报原来的错误。仔细看这三个类,也只是普通的Fragment,
跟别得Fragment并没有什么不同。这下就奇怪了,实在是找不到原因了。上网查资料,说的都差不多,build.gradle文件中这个问题由于项目中类太多,方法太多。 Android平台的Java虚拟机Dalvik在执行DEX格式的Java应用程序时,使用原生类型short来"multiDexEnabled true"也加入了。
看了下classloader机制,很多字,但是并没有看出解决问题的方法。实在不知道该怎么办了,报错的类是以前的人基于
http自己写的一个网络框架,就想着,实在不行就把以前的网络请求框架换了吧,当然这也不是一个简单的事。而且就算
换了,也不能确定能决绝问题,迷茫中。。。
后来,看到一些关于dex的问题,于是就搜到一遍文章。我就照着上面的方法,在项目中加了两行代码,奇迹,竟然跑起来了,于是我把删除的类渐渐加进去,直到最后一个,都能
正常运行,真是欣喜若狂。
解决方法就是在项目的Application类中加入了以下代码:
@Override protected void attachBaseContext(Context base) { super.attachBaseContext(base); MultiDex.install(this); }
索引DEX文件中的方法。这意味着单个DEX文件可被引用的方法总数被限制为65536。通常APK包含一个classes.dex文件,因此Android应用
的方法总数不能超过这个数量,这包括Android框架、类库和你自己开发的代码。这个问题可以通过将一个DEX文件分拆成多个DEX文件解决。
而上面的代码就是将一个DEX文件分拆成多个DEX文件,完美解决NoClassDefFoundError。