MultiDex

2024-05-29 07:18
文章标签 multidex

本文主要是介绍MultiDex,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

原文转自:http://coolpers.github.io/multidex/2015/04/13/multidex.html


1.MultiDex的产生背景

当Android系统安装一个应用的时候,有一步是对Dex进行优化,这个过程有一个专门的工具来处理,叫DexOpt。DexOpt的执行过程是在第一次加载Dex文件的时候执行的。这个过程会生成一个ODEX文件,即Optimised Dex。执行ODex的效率会比直接执行Dex文件的效率要高很多。但是在早期的Android系统中,DexOpt有一个问题,DexOpt会把每一个类的方法id检索起来,存在一个链表结构里面。但是这个链表的长度是用一个short类型来保存的,导致了方法id的数目不能够超过65536个。当一个项目足够大的时候,显然这个方法数的上限是不够的。尽管在新版本的Android系统中,DexOpt修复了这个问题,但是我们仍然需要对低版本的Android系统做兼容。

为了解决方法数超限的问题,需要将该dex文件拆成两个或多个,为此谷歌官方推出了multidex兼容包,配合AndroidStudio实现了一个APK包含多个dex的功能,详见。

2.MultiDex的简要原理

我们以APK中有两个dex文件为例,第二个dex文件为classes2.dex。

1、 兼容包在Applicaion实例化之后,会检查系统版本是否支持 multidex,classes2.dex是否需要安装。

2、 如果需要安装则会从APK中解压出classes2.dex并将其拷贝到应用的沙盒目录下。

3、 通过反射将classes2.dex注入到当前的classloader中。

3.MultiDex的使用

一、应用程序的修改:

引入multidex兼容包,如果自定义了Application类,则使其继承自MultiDexApplication。否则在manifest文件的application标签中增加android:name=”android.support.multidex.MultiDexApplication”

二、构建脚本修改:

AndroidStudio使用的构建工具是gradle,而我们使用的是ant,所以需要在目前的ant脚本中增加对multidex的支持,步骤如下:

1、 更新AndroidSDK,确保build-tools有21.1.2版本,proguard在4.10以上,并将其添加到系统的环境变量。

2、 运行dx –help如下结果:

–multi-dex选项,开始认为只要将它打开就可以了,但打完包启动后会崩溃,查看log发现有的类在Application类初始化的时候没有被加载,这些类被打包在了第二个dex文件中。

继续看上面的选项列表,–multi-dex选项后面有两个可选的选项。

–main-dex-list=<file>:参数是一个类列表的文件,在该文件中的类会被打包在第一个dex中。

–minimal-main-dex:只有在–main-dex-list文件中指定的类被打包在第一个dex,其余的都在第二个dex文件中。

我们只需要使用–main-dex-list,将Application初始化所需要的类放在一个文件中即可。

3、 生成main-dex-list列表:</br>Android SDK的build-tools中有一个mainDexClasses脚本。

该脚本要求输入一个文件组(包含编译后的目录或jar包),然后分析文件组中的类并写入到–output所指定的文件中,如classes_to_kepp_in_main_dex文件。

4、 –set-max-idx-number:这个选项没有被列出,其能够限定每个dex文件中最大的方法数,这里设置每个dex的最大方法数为52900。

5、 将第二个dex打包到APK中:使用aapt命令,aapt add 。

综上所属,修改后的脚本如下:

<condition property="multi-dex-ospath"value="${basedir}\${outdir}"else="${basedir}/${outdir}" ><os family="windows"/>
</condition>	
<condition property="mainDexClasses" value="${android-build-tools}/mainDexClasses.bat" else="${android-build-tools}/mainDexClasses" ><os family="windows"/>
</condition>	
<path id="commonjars"><fileset dir="${external-libs}"><include name="android-support-*.jar"></include><include name="imageloader_*.jar"></include><include name="clientupdate_*.jar"></include><include name="MaRuntime_*.jar"></include><include name="pushservice-*.jar"></include></fileset>
</path>
<target name="multidex" depends="compile"><echo>dex:Converting compiled files and external libraries into ${outdir}...</echo><path id="inputdir"><pathelement location="${outdir-classes}"/><path refid="commonjars"/></path><property name="files" refid="inputdir"/><condition property="realfiles" value=""${files}"" else="${files}" ><os family="windows"/></condition><exec executable="${mainDexClasses}" failonerror="true" ><arg line="--output ${multi-dex-ospath}/classes_to_kepp_in_main_dex"/><arg value="${realfiles}"/></exec><apply executable="${dx}" failonerror="true" parallel="true"><arg value="--dex" /><arg value="--multi-dex" /><arg value="--main-dex-list=${multi-dex-ospath}/classes_to_kepp_in_main_dex"/><arg value="--set-max-idx-number=52900" /><arg value="--output=${multi-dex-ospath}" /><arg path="${outdir-classes}" /><fileset dir="${external-libs}" includes="*.jar"/><fileset dir="${appsearch-ui-path}/libs" includes="*.jar"><exclude name="android-support-v4.jar"/></fileset></apply>
</target>	
<property name="second_dex" value="classes2.dex" />
<property name="second_dex_path" value="${multi-dex-ospath}/${second_dex}" />	
<target name="seconddex-check"><condition property="has-second"><available file="${second_dex_path}" /></condition>
</target>

打包后运行,程序正常启动。

4. 遇到的问题

1、 mainDexClasses脚本在windows和linux下文件组的参数形式不同。 在windows下,脚本中的shift会将文件分隔符“;”替换成空格,导致参数获取错误,在文件组外部增加双引号,解决了该问题。

2、 生成文件组的jar包通配符问题,使用path和fileset解决了该问题。

3、 multidex兼容包创建目录失败的问题,参见:https://code.google.com/p/android/issues/detail?id=79388&q=multidex%20Failed%20to%20create%20dir&colspec=ID%20Type%20Status%20Owner%20Summary%20Stars

这篇关于MultiDex的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1012999

相关文章

Exception_android_java.util.zip.ZipException: duplicate entry:android/support/multidex/MultiDex

java.util.zip.ZipException: duplicate entry:android/support/multidex/MultiDex.class gradle里面的配置multiDexEnabled true和导入android-support-multidex.jar包二者会重复   defaultConfig {         targetSdkVersion

Android 解决65535的限制 使用android-support-multidex解决Dex超出方法数的限制问题,让你的应用不再爆棚

随着应用不断迭代,业务线的扩展,应用越来越大(比如集成了各种第三方sdk或者公共支持的jar包,项目耦合性高,重复作用的类越来越多),相信很多人都遇到过如下的错误: [java]  view plain copy UNEXPECTED TOP-LEVEL EXCEPTION:   java.lang.IllegalArgumentException: method

Android之failed for task ‘:app:dexDebug‘致gradle编译OOM问题解决(android-support-multidex)

当我们的业务越来越多,项目里面的方法和第三方的jar包也会越来越多,然后昨晚就遇到了下面这个问题   UNEXPECTED TOP-LEVEL EXCEPTION:at com.android.dx.merge.DexMerger.readSortableTypes(DexMerger.java:596)at com.android.dx.m

Android热修复三部曲之MultiDex 分包架构

在上一篇博客中,讲解了使用Ant打包的流程,也编写了相应的脚本代码。但是忘了说明怎么运行了。有两种方式: 在Eclipse的build.xml 中,右键run as 即可。通过命令行形式进入到当前工程目录下,输入命令ant 工程名。 上一篇漏下的已经补充。下面开始今天博客的主要内容。 该篇博客主要分为三个部分: 什么是分包架构分包架构的好处怎么实现分包 什么是分包架构 如果反

Andrlid Studio报错:Failed to resolve: com.android.support:multidex-instrumentation:1.0.1

https://www.jianshu.com/p/8b6227567c0e   解决办法,加入: maven {url 'https://maven.google.com'}   Error:Failed to resolve: com.android.support:multidex:1.0.2 --AndroidStudio 3.0  T9的第三个三角 关注 20

Android中MultiDex优化

MultiDex基本思路         当一个Dex文件太肥的时候(方法数目太多、文件太大),在打包或在安装或运行apk也会出问题。 解决方法就是将这个硕大的Dex文件拆分成若干个小的Dex文件。 刚好一个ClassLoader可以有多个DexFile。         MultiDex主要性能瓶颈         解压缩和Dex优化(dexopt)

【Flutter/Android】新建项目,打开android 目录,报错红色以及开启 MultiDex 配置

1 报错红色问题。 单独打开 Flutter 项目下的 android 项目即可。 也就是说,你要一部分原生代码开发,你就需要自己把 android 项目单独出去做(其实就相当于android 项目引用 Flutter的dart部分)。也就是说,在 Flutter 项目里打开 android 目录是没啥意义的,你要配置 安卓端,就自己单独打开 android 目录。所以爆红是很正常的(只要不报错

Android MultiDex实践:如何绕过那些坑?

本文是我的同事徐冬投稿,介绍他在方法数到达65k上限后,应用官方MultiDex方案时踩过的一些坑,以及如何解决这些棘手问题的实践过程。 前言 Android应用65k方法数的限制一直为广大开发者所诟病,在应用功能越来越丰富、各种开源库越来越多的今天,65k方法数瓶颈俨然已是一大绊脚石。 关于65k方法数限制的更多细节可以看下冯建的这篇文章: http://www