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。 

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

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

    1.HashMap底层原理分析(put.get方法) HashMap底层是通过数组加链表的结构来实现的.HashMap通过计算key的hashCode来计算hash值,只要hashCode一样,那ha ...

  2. Android 打开方式选定后默认了改不回来?解决方法(三星s7为例)

    Android 打开方式选定后默认了改不回来?解决方法(三星s7为例) 刚刚在测试东西,打开一个gif图,然后我故意选择用支付宝打开,然后...支付宝当然不支持,我觉得第二次打开它应该还会问我,没想到 ...

  3. Android Studio2.x版本无法自动关联源码的解决方法

    Android Studio2.x版本无法自动关联源码的解决方法 在学习android开发过程中,对于一个不熟悉的类,阅读源码是一个很好的学习方式,使用andorid studio开发工具的SDK M ...

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

    android Run模式也会出现"Waiting for debugger"的解决方法 出现“waiting for debugger”窗口是在debug模式下运行出现的.但是, ...

  5. Android视图SurfaceView的实现原理分析(示例,出错代码)

    在Android系统中,有一种特殊的视图,称为SurfaceView,它拥有独立的绘图表面,即它不与其宿主窗口共享同一个绘图表面.由于拥有独立的绘图表面,因此SurfaceView的UI就可以在一个独 ...

  6. Android DecorView 与 Activity 绑定原理分析

    一年多以前,曾经以为自己对 View 的绘制已经有了解了,事后发现也只是懂了些皮毛而已.经过一年多的实战,Android 和 Java 基础都有了提升,时机成熟了,是时候该去总结 View 的绘制流程 ...

  7. Junit 注解 类加载器 .动态代理 jdbc 连接池 DButils 事务 Arraylist Linklist hashset 异常 哈希表的数据结构,存储过程 Map Object String Stringbufere File类 文件过滤器_原理分析 flush方法和close方法 序列号冲突问题

    Junit 注解 3).其它注意事项: 1).@Test运行的方法,不能有形参: 2).@Test运行的方法,不能有返回值: 3).@Test运行的方法,不能是静态方法: 4).在一个类中,可以同时定 ...

  8. Android 中 ListView Adapter getView 被多次调用问题 解决方法

    执行多次原因是因为每显示一个VIew,它都去测量view的高度,执行measure方法,导致getView执行多次. 解决方法是将 ListView 的 layout_width 设置为 fill_p ...

  9. Android通过Chrome Inspect调试WebView出现404页面的解决方法

    无论是调试Web页面还是调试Hybrid混合应用,只要是调试Android的webview,都需要使用Chrome://inspect进行调试.但是国内开发者会出现404 Not Found错误: 解 ...

随机推荐

  1. mysql多表查询 查询排序

    有 ask 问题表  和 answer回答表  回答表中的ask_id和 ask表中的id对应 1.查询 /*查询回答了的 */select a.id,a.title,count(b.ask_id) ...

  2. Zookeeper的临时节点和永久节点

    Zookeeper中节点分为两种:临时节点和永久节点. 临时节点有一个节点: 当创建临时节点的程序停掉之后,这个临时节点就会消失. 更直观的,如下   Persistent是临时节点. Persist ...

  3. Unity Sprite Packer 问题集合

    介绍 今天突发奇想用了下sprite packer 这个功能,基本用法网上教程一堆一堆的,这里就不赘述了. 在使用sprite packer过程中遇到一些问题,然后各种百度不到答案,最后和谐上网找到了 ...

  4. jq-文本框只能输入数字

    <input type="text" onKeyUp="value=value.replace(/\D/g,'')"  /> onKeyUp: 当输 ...

  5. SpringAop--系统日志简例

    通过Spring的Aop我们可以声明式的配置事务管理,那么同样可以通过SpringAop来进行处理的系统日志该如何实现呢? 一.数据表和实体类的准备 我们要管理系统日志,那么数据表和实体类是必不可少的 ...

  6. Java_注解之二

    在上一次的注解案例里面配置注解的同时,也添加了一对多(@OneToMany)的关系在里面. 本次将补充上次的缺失:其他三种关联方式的配置. 为了简化配置的复杂度   在此案例中Emp和Dept并不是唯 ...

  7. 解决Android弹出软键盘导致的问题

    一.当Activity启动后EditText直接获取了焦点,此时软键盘会自动弹出,这种体验并不是很好,因此要做的Activity启动不自动弹出软键盘,只需要在Manifest中对应的Activity添 ...

  8. GitHub代码托管平台搭建

    GitHub代码托管平台搭建 注册账户以及创建仓库 要想使用github第一步当然是注册github账号了, github官网地址:https://github.com/. 之后就可以创建仓库了(免费 ...

  9. C#调用Win32 api时的内存操作

    一般情况下,C#与Win 32 Api的互操作都表现的很一致:值类型传递结构体,一维.二维指针传递IntPtr.在Win32 分配内存时,可以通过IntPtr以类似移动指针的方式读取内存.通过IntP ...

  10. windows下使用批处理设置环境变量

    1. 设置临时环境变量 set BAT_HOME=c:\bat 此命令只对当前窗口有效,批处理或cmd窗口一关闭,变量就恢复原来的值了. 2. 设置永久环境变量 方法一 setx BAT_HOME C ...