Android 65K问题之Multidex原理分析及NoClassDefFoundError的解决方法
2016-04-25 14:25
686 查看
Android 65K问题相信困惑了不少人,虽然AS的出来可以通过分dex快速解决65K问题,但是同时也容易因为某些代码没有打包到MainDex里引起NoClassDefFoundError。随着5.0的推出,Android也放出了Multidex
Support Library来解决这个问题。
Multidex Support
Library可以直接分包处理65K问题,并且不会发生NoClassDefFoundError的情况。
1.使用的话,首先添加依赖库:
2.另外开启Multidex开关:
3.这时候运行的话可能会报java堆内存错误,因此最好添加上:
4.如果你有自己的Application,则修改一下Application使其继承MultiDexApplication
这时候你就可以跑了,具体可以看官方文档,毕竟官方文档里面写得非常清楚。
下面我们主要来说下Multidex的实现方法,以下部分来源:http://blog.waynell.com/2015/04/19/android-multidex/ 的分析。
Multidex的实现原理
Multidex的实现原理是将class编译进不同的classes.dex文件中,一般情况下,一个APK文件中只包含了一个classes.dex文件。分包之后就存在一个主的classes.dex,多个副的classes2.dex,classes3.dex…
在要启动程序时,Android会先去加载主的classes.dex,然后在程序启动后再去加载其它副的dex。那哪些class应该被编译到主的classes.dex中呢?
先来看下Multidex的编译过程,它由三个不同的gradle task组成:
这个task会读取项目的AndroidManifest.xml文件中注册的application、Activity、service、receiver、provider、instrumentation相关类,并将其class文件路径写到文件
这个task会调用ProGuard并根据上一步生成的manifest_keep.txt文件内容去压缩class,剔除没有用到的class,生成一个精简的jar包
这个task会根据上一步生成的componentClasses.jar去寻找这里面的各个class文字中依赖的class,比如一个class中有一成员变量X,那么X就是依赖的class,componentClasses.jar中所有的class和依赖的class路径都会被写入到文件
通过上面的分析,我们已经得知Multidex的原理了,所以要解决一启动程序就NoClassDefFoundError的问题只需要确定该类是否正确被编译到主classes.dex中去了,如果没有被编进去的话,只要修改下maindexlist.txt文件,把这个类添加进去即可。由于maindexlist.txt这个文件是每次编译时自动生成的,手动去修改它是没用的,所以我们可以在gradle编译中新加入一个task,在
转自:http://blog.csdn.net/hjhrq1991/article/details/51008734
Support Library来解决这个问题。
Multidex Support
Library可以直接分包处理65K问题,并且不会发生NoClassDefFoundError的情况。
1.使用的话,首先添加依赖库:
//分包multiDexEnabled必须添加该依赖 compile 'com.android.support:multidex:1.0.1'
2.另外开启Multidex开关:
buildTypes { release { minifyEnabled false //分包 multiDexEnabled true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } }
3.这时候运行的话可能会报java堆内存错误,因此最好添加上:
dexOptions { javaMaxHeapSize "4g" incremental true }
4.如果你有自己的Application,则修改一下Application使其继承MultiDexApplication
public class MyApplication extends MultiDexApplication { ... }如果你的Application很不幸已经继承了其他Application导致无法继承MultiDexApplication的话,那也是可以是,只需要复写该方法并加上该代码:
@Override protected void attachBaseContext(Context base) { super.attachBaseContext(base); MultiDex.install(base); }
这时候你就可以跑了,具体可以看官方文档,毕竟官方文档里面写得非常清楚。
下面我们主要来说下Multidex的实现方法,以下部分来源:http://blog.waynell.com/2015/04/19/android-multidex/ 的分析。
Multidex的实现原理
Multidex的实现原理是将class编译进不同的classes.dex文件中,一般情况下,一个APK文件中只包含了一个classes.dex文件。分包之后就存在一个主的classes.dex,多个副的classes2.dex,classes3.dex…
在要启动程序时,Android会先去加载主的classes.dex,然后在程序启动后再去加载其它副的dex。那哪些class应该被编译到主的classes.dex中呢?
先来看下Multidex的编译过程,它由三个不同的gradle task组成:
collect{variant}MultiDexComponents task
这个task会读取项目的AndroidManifest.xml文件中注册的application、Activity、service、receiver、provider、instrumentation相关类,并将其class文件路径写到文件
buidl/intermediates/multi-dex/${variant.dirName}/manifest_keep.txt中
shrink{variant}MultiDexComponents task
这个task会调用ProGuard并根据上一步生成的manifest_keep.txt文件内容去压缩class,剔除没有用到的class,生成一个精简的jar包
buidl/intermediates/multi-dex/${variant.dirName}/componentClasses.jar
create{variant}MainDexClassList task
这个task会根据上一步生成的componentClasses.jar去寻找这里面的各个class文字中依赖的class,比如一个class中有一成员变量X,那么X就是依赖的class,componentClasses.jar中所有的class和依赖的class路径都会被写入到文件
buidl/intermediates/multi-dex/${variant.dirName}/maindexlist.txt中,这个文件中的类都会被编译进主的classes.dex中去。(详情可以查看ClassReferenceListBuilder的实现源码)
NoClassDefFoundError
Multidex固然是好的,不用再为方法数超过65536而苦恼了。但是有时往往会带来意想不到的bug,比如NoClassDefFoundError。之前我就在项目中遇到了这个问题,一启动程序就crash了,看log是由于某个类找不到引起的。通过上面的分析,我们已经得知Multidex的原理了,所以要解决一启动程序就NoClassDefFoundError的问题只需要确定该类是否正确被编译到主classes.dex中去了,如果没有被编进去的话,只要修改下maindexlist.txt文件,把这个类添加进去即可。由于maindexlist.txt这个文件是每次编译时自动生成的,手动去修改它是没用的,所以我们可以在gradle编译中新加入一个task,在
create{variant}MainDexClassList这个task完成之后再去修改maindexlist.txt文件添加丢失的class。
转自:http://blog.csdn.net/hjhrq1991/article/details/51008734
相关文章推荐
- 运行android时Unable to resolve target 'Google Inc.:Google APIs:7'错误
- android log分析
- Chromebook 也许很快就能运行所有的 Android 应用
- 记一次内存泄露优化过程
- 对android应用安装程序apk反编译与分析(二)-jad将class文件转化为java文件
- Android 65K问题之65K来源探究
- Android 可拖拽的GridView效果实现, 长按可拖拽和item实时交换
- js和Android 的互相调用
- android监听通讯录内容变化
- Found 2 versions of android-support-v4.jar in the dependency list,but not all the versions are ident
- Android Studio 生成 Xutils3 注入的插件
- Android Studio系列教程五--Gradle命令详解与导入第三方包
- DataBinding 坑爹问题集
- Android Studio系列教程六--Gradle多渠道打包
- Android Studio系列教程四--Gradle基础
- java代码中实现android背景选择的selector-StateListDrawable的应用
- Android 获取签名和android studio设置签名
- android中怎么把控件隐藏
- android 拨打电话与发送短信
- android技术开发