dex分包方案概述与multidex包的配置使用
参考资料:
Android dex分包方案
Android分包MultiDex原理
《Android开发艺术探索》
博客中间会涉及到dex文件的反编译,参考博文:
dex文件的反编译-dex2jar和jd-gui
1.dex分包的原因
对于功能越来越复杂的app的两大问题
问题一:当项目越来越大,方法数超过65536,编译时会出错(为什么是65536,参考下面关于dexopt对方法id检索存储介绍),这个所说的方法数包含用到的框架,依赖的jar包,当然还有我们应用本身的代码中的所有方法。
我们可以写个Demo看看报的具体错误。那我们写个65536以上个方法,可以用java的IO流向一个txt里写入65537个方法。
public class MethodWriter {public static void main(String[] args) throws IOException{FileWriter fw = new FileWriter("demo.txt");for(int i = 1 ; i <= 65537; i++){fw.write( "public void me" + i + "(){ }\r\n" );fw.flush();}fw.close();}
}
然后复制txt文件里的方法到AS工程里即可。注意,将这些方法分别放在几个类下面,保证每个类不要超过65536。我们所说的65536限制是整个项目的限制。下面,我们分两种方案放置这些方法,运行项目,看看AS会有什么结果。
方案一:我们自己应用的方法数超过了65536
我们所说的方法数限制,这个方法数包括了jar包,框架,还有我们自己应用的代码,当我们应用的代码超过65536时,结果如下:
我们看到,显示我们方法的引用是65579.而引用数最大是65536,建议我们开启分包方案。
方案二:我们应用的方法数没有超过65536,但是加上依赖的jar包,框架等,超过了65536(根据方案一的结果,我们应用方法数是65579,那我们删掉200个方法,就小于65536)
报错如下:
- 问题二:方法数并没有超过65536,编译也完成了,但是在android2.3以前的系统安装的时候,会异常中止安装。
这个问题会发生在Android 2.2以及Android 2.3的设备上,涉及到一个名为dexopt的程序,全称dex optimization,即dex文件优化程序。在优化过程中,dexopt采用一个固定大小的缓冲区(LinearAlloc)来存储应用中所有方法的信息,那么之所以会出现在老版本停止安装,是因为老版本的缓冲区的大小是5M,而在新版本中,这个缓冲区的大小是8M或者16M,在老版本中更容易超过这个限制。
dexopt的执行过程是在第一次加载dex文件的时候执行的。这个过程产生了一个ODEX文件,全称Optimised Dex。这个ODEX文件是在安装过程中从apk里提取出的可运行文件,是优化dex产生的,再把apk包里的dex文件删除,这样就做到了预先提取。如果没有ODEX文件,那么系统会从apk包中提取dex然后再运行。所以优化后可以加快软件的启动速度,预先提取,减少对RAM的占用。
在早期的Android系统中,dexopt会把每一个类的方法id检索起来,存在一个链表结构里,而这个链表的长度是用一个short类型来保存的,导致方法id的数目不能够超过65536个。虽然新版本的android系统中,dexopt修复了这个问题,但是老版本的android系统的用户市场占有率还是占一定比例,还是不能放弃这部分用户的,所以我们在开发中需要对老版本的这个问题进行兼容。
2.方法数越界的解决方案
插件化技术
我们可以采用动态加载部分dex,通过将一个dex拆分成两个或多个dex,解决方法数越界的问题。
插件化是一套重量级的技术方案,我们需要通过反射来调用插件的类或方法,要使用一套插件框架来配合,而且插件化适合一些独立的模块,兼容性问题往往较多,如果只是用于解决方法数越界的话,并不是最好的方案。
multidex解决方案
为了解决方法数越界的问题,Google在2014年提出了multidex的解决方案,这个方案主要是针对AndroidStudio和Gradle编译环境的,将一个dex文件拆成两个或多个dex文件。
不过需要注意的是multidex有一个版本问题,在Android 5.0以前使用multidex需要手动引入Google提供的android-support-multidex.jar这个jar包。这个jar包我们可以在Android SDK目录下的extras/android/support/multidex/library/libs下找到。而从Android 5.0开始,Andorid默认支持了multidex。
所以,我们就需要注意我们的SDK版本了,如果已经支持了multidex,而我们又把android-support-multidex.jar放在了项目的libs文件下,就会报错。
3.在Gradle和代码中配置使用Multidex
在Gradle中配置使用Multidex
由于Android的Gradle插件在Android Build Tool 21.1开始支持使用multidex,所以我们需要使用Android Build Tools 21.1及以上版本,修改app目录下的build.gradle文件,有两点需要修改。
(1)在defaultConfig中添加multiDexEnabled true这个配置项。
(2)在dependencies中添加multidex的依赖:
compile ‘com.android.support:multidex:1.0.0’注意buildToolsVersion要高于21.1,配置好如下:
在Gradle中配置好之后,我们还需要在代码中加入支持multidex的功能,有三种方案可选
方案一:在manifest文件中指定Application为MultiDexApplication,如下:
方案二:写一个Application类并继承MultiDexApplication,并在AndroidManifest.xml的application标签中进行注册(在application标签中增加name属性,并添加自己的Application类名即可),如果不是想重写MultiDexApplication中一些方法的话,还是方案一更方便些。如下:![这里写图片描述](https://img-blog.csdn.net/20160722091032626)注册如下:![这里写图片描述](https://img-blog.csdn.net/20160722091043813)方案三:如果不想按方案二继承,我们可以重写Application的attachBaseContext方法,注意,这个方法比onCreate方法先执行。具体方法是创建一个新类,继承Application,然后重写attachBaseContext方法,并在AndroidManifest.xml的application标签中进行注册(与方案二注册相同)如下:![这里写图片描述](https://img-blog.csdn.net/20160722091212737)对于在AndroidManifest.xml中注册,与方案二的注册相同。
3.使用Multide分包后两种情况的结果
我们的Demo图如下,我们根据该图和dex文件反编译的结果分析分包情况。
情况一:方法数没有越界
我们将方法数控制在65536以内,方法数没有越界的话,是不会分包的,解压apk,你会发现apk里只有一个classes.dex,如下将其反编译后(不知道怎么反编译的可以看一下这篇博文:http://blog.csdn.net/gaozhan_csdn/article/details/51984056),结果如下:
可以发现,我们的类都在这个主dex文件里,并没有分包。
情况二:方法数越界
我们再将方法数增加到65536以上。解压apk,结果如下:
对三个dex文件反编译一下,看看它们里面分别都包含了什么类。
classes.dex(主dex)下的类视图:
classes2.dex的类视图
classes3.dex的类视图
可以发现Second类和Third类分别在classes2.dex文件和classes3.dex文件里,其他类都在主dex文件里(classes.dex),我们用multidex的确实现了分包从而解决了方法数越界的问题。
4.使用MultiDex存在的一些问题
MultiDex使用起来很方便,但它也有一定的局限性。先总结一下网上查到的,后续研究。
由于需要加载额外的dex文件,应用的启动速度会降低,当其他dex文件较大的时候,甚至会出现ANR现象。
由于Dalvik linearAlloc的Bug,有可能导致使用multidex的应用无法在Android4.0以前的手机上运行。也是这个bug,可能出现应用在运行中由于采用了multidex方案从而产生大量内存消耗的情况,导致应用崩溃。
小结与后续:
- multidex涉及版本问题,所以使用的时候一定要注意,不同版本该不该手动导包
- 分包后,由于dex的加载问题,可能会出现找不到类的问题,所以我们需要研究一下如何将某个具体的类按我们的意愿放入到某个dex里
- multidex源码
- dex如何加载,加载机制
dex分包方案概述与multidex包的配置使用相关推荐
- Android dex分包方案 (多dex)
原文地址: http://my.oschina.net/853294317/blog/308583 当一个app的功能越来越复杂,代码量越来越多,也许有一天便会突然遇到下列现象: 1. 生成的apk在 ...
- dex分包之--------multidex包的配置使用
目录: 一.前言 二.产生原因 三.MultiDex的简要原理 四.MultiDex的使用 一.前言 首先说一下我遇到的情况,最近接手了一个项目是在已有的项目里进行更新添加一些功能,然后该项目导了N多 ...
- Android分包方案multidex
对于功能越来越复杂的app的两大问题 一:我们自己应用的方法数超过了65536 我们所说的方法数限制,这个方法数包括了jar包,框架,还有我们自己应用的代码,当我们应用的代码超过65536时,结果如 ...
- Android Multidex(dex分包)
Android Multidex(dex分包) 分包: 一个dex分成多个dex 什么要分包 单个 Dalvik Executable (DEX) 中, 可调用的最大的引用总数为 65536 ,若超过 ...
- 【Android 热修复】热修复原理 ( 多 Dex 打包机制 | 多 Dex 支持 | Dex 分包设置 | 开发和产品风格设置 | 源码资源 )
文章目录 一.Dex 打包设置 1.多 Dex 支持 2.Dex 分包设置 3.开发和产品风格设置 ( 非必须 ) 二.完整 build.gradle 配置 1.build.gradle 配置 2.d ...
- Cocos Creator基于热更新的分包方案
cocos 的热更新是基于对比本来文件列表和远程文件列表的md5实现的,如果有多个远程资源库,就可以拿来作为分包方案.大概流程是这样的: 一 确定分包策略 首先是,策划要根据一定的策略,将动态加载的资 ...
- 一文搞懂全链路监控:方案概述与比较 | 干货
原文标题为<全链路监控(一):方案概述与比较>,作者陶邦仁,链接:https://www.jianshu.com/p/92a12de11f18 0 - 问题背景 随着微服务架构的流行,服务 ...
- Android DEX加固方案与原理
Android 反编译的威胁 逆向分析: 漏洞挖掘.协议分析 二次打包: 盗版.破解.广告 保护方案 代码混淆:Java代码.C\C++带马甲.JS\HTML代码 应用加固:DEX文件.SO文件.资源 ...
- 点歌服务器工作原理,KTV点歌系统方案概述
<KTV点歌系统方案概述>由会员分享,可在线阅读,更多相关<KTV点歌系统方案概述(7页珍藏版)>请在人人文库网上搜索. 1.一)目前点歌系统的主流方式目前,可以实现的KTV系 ...
最新文章
- XHTML行内描述性元素(持续更新中)
- 百度地图JavaScript API覆盖物旋转时出现偏移
- ASP.NET Core 中间件分类
- Ext JS 4.1 RC1发布
- 一朵落地中国的“智能云”是如何飘到你身边的!
- 创建多模块springcloud应用eureka server和client和消费端demo
- 用AngularJS开发下一代Web应用pdf
- 可靠产品设计的5项技术 02-识别和评估关键的可靠性风险
- 【语音定时播报系统】基于树莓派+百度语音合成打造语音定时播报系统
- 用 QT实现拖放(drag-drop)功能
- mysql cbrt函数_PostgreSQL学习笔记5之函数和操作符一
- win10安装Geany编辑器
- 公众号 多服务器配置_公众号发布的文章越多,涨粉越多吗?
- word 插入分隔符实现章节单独编页
- 如何做好提升领导力培训PPT课件?
- 深入理解计算机系统 2.1 节信息存储,深入理解计算机系统(原书第3版)- 第2章 信息的表示和处理 笔记...
- 数据库管理 │ 浅谈从集中式到分布式数据库的转型要点
- matlab rand randn 每次生成的随机数都一样的解决方案
- Polkadot(波卡链):白皮书-畅想一种异构的多链架构
- 【第二季】Arcgis地图制图基础|(一)Arcgis地图符号制作