Android 65K问题之Multidex原理分析及NoClassDefFoundError的解决方法

Android 65K问题相信困惑了不少人,尽管AS的出来能够通过分dex高速解决65K问题,可是同一时候也easy由于某些代码没有打包到MainDex里引起NoClassDefFoundError。

随着5.0的推出,Android也放出了Multidex
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组成:

1
collect{variant}MultiDexComponents task

这个task会读取项目的AndroidManifest.xml文件里注冊的application、Activity、service、receiver、provider、instrumentation相关类,并将其class文件路径写到文件buidl/intermediates/multi-dex/${variant.dirName}/manifest_keep.txt

1
shrink{variant}MultiDexComponents task

这个task会调用ProGuard并依据上一步生成的manifest_keep.txt文件内容去压缩class,剔除没实用到的class。生成一个精简的jar包buidl/intermediates/multi-dex/${variant.dirName}/componentClasses.jar

1
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。

时间: 2024-10-06 09:58:22

Android 65K问题之Multidex原理分析及NoClassDefFoundError的解决方法的相关文章

HashMap底层原理分析(put、get方法)

1.HashMap底层原理分析(put.get方法) HashMap底层是通过数组加链表的结构来实现的.HashMap通过计算key的hashCode来计算hash值,只要hashCode一样,那hash值就是相同的.当hash值相同时,就会出现hash冲突,HashMap通过链表来解决冲突. 原理图: 实例: import java.util.HashMap; import java.util.Map; ? public class HashMapTest { public static vo

Android SDK更新 Connection to http://dl-ssl.google.com refused 解决方法

原地址:http://blog.csdn.net/foxeatapple/article/details/8450372 问题描述 使用SDK Manager更新时出现问题Failed to fetch URL https://dl-ssl.google.com/android/repository/repository-6.xml, reason: Connection to https://dl-ssl.google.com refusedFailed to fetch URL http:/

android docs本地帮助文档打开特别慢的解决方法

1.断网,使用IE打开 2.使用火狐浏览器脱机浏览 android docs本地帮助文档打开特别慢的解决方法,布布扣,bubuko.com

android Run模式也会出现"Waiting for debugger"的解决方法

android Run模式也会出现"Waiting for debugger"的解决方法 出现“waiting for debugger”窗口是在debug模式下运行出现的.但是,今天我在run模式下也出现了此窗口,并且一直如此.卸载程序重新运行也是如此.android真机在脱离电脑的情况下,会一直死在“waiting for debugger”的. run 后eclipse 就直接跳出 The JAR /home/xxx/.../android.jar has no source a

Android视图SurfaceView的实现原理分析

附:Android控件TextView的实现原理分析 来源:http://blog.csdn.net/luoshengyang/article/details/8661317 在Android系统中,有一种特殊的视图,称为SurfaceView,它拥有独立的绘图表面,即它不与其宿主窗口共享同一个绘图表面.由于拥有独立的绘图表面,因此SurfaceView的UI就可以在一个独立的线程中进行绘制.又由于不会占用主线程资源,SurfaceView一方面可以实现复杂而高效的UI,另一方面又不会导致用户输

(转)Android工程出现 java.lang.NoClassDefFoundError错误解决方法

在Eclipse中,导入Android工程,工程没有报错,运行时,出现 java.lang.NoClassDefFoundError类没有找到的错误.从问题上可以看出是导入包出错的原因.遂百度加谷歌. 问题出在:ADT高版本的原因 把引入的第三方包放在Referenced Libraries中,ADT升级到17后就出现了Android Dependencies,所以如果程序中引入的第三方包没有在Android Dependencies中时,就会报文章开头的错. 解决方法: 先移除之前的Refer

Android statusbar 透明后 toolbar与之重叠问题的解决方法

之前想要给statusbar和toolbar实现这样的效果: 为使得statusbar变为透明,在自定义theme中给statusbar添加了以下属性: <item name="android:windowTranslucentStatus">true</item> 可是在statusbar变透明后界面却变成下图这个样子:(即toolbar悬浮在statusbar之后) 为了说明情况,我用另一个更明显的界面来解释: 起初我简单粗暴的为toolbar加了一个mar

android Listview 与 Scrollview 共存的一个较优良的解决方法

最近因为一个项目需要在Scrollview里面嵌套一个Listview,如果只是用android提供的ListView是什么效果大家肯定都已经知道了,经过摸索,自己找到了一个还算可以的解决方法,如下所示: 首先时自定义一个MyListview继承Listview ,重写他的onMeasure方法 ,让它不能滚动,代码如下: 基本这样就解决了它俩共存的问题,但是新问题来了,每次加载时,都是MyListview优先显示(而且好像是从MyListview底部向上开始显示的,因为我的测试数据太少,可能说

我的Android进阶之旅------&amp;gt;Android编译错误java.util.zip.ZipException: duplicate entry的解决方法

今天在Android Studio中把另外一个项目引入当前项目,编译的时候出现了java.util.zip.ZipException: duplicate entry错误. 错误例如以下所看到的: FAILURE: Build failed with an exception. * What went wrong: Execution failed for task ':watch:packageAllDebugClassesForMultiDex'. > java.util.zip.ZipEx