Android dex分包
来源:互联网 发布:js字符串去空格转数组 编辑:程序博客网 时间:2024/06/16 05:18
Android中使用Dalvik虚拟机来运行应用程序,Dalvik虚拟机是有Google公司为Android平台量身定制的,它支持运行.dex格式的Java应用程序的运行。.dex文件将所有的.class文件打包,是专门Dalvik设计的一种压缩格式。Android项目在打包成APK时,项目中所有的.class文件都已被打包在.dex文件中了。在Android系统安装一个应用时,会对.dex文件进行优化,这个过程由专门的工具来处理,这个工具叫做DexOpt。DexOpt在第一次加载.dex文件时启动,这个过程会产生一个ODEX文件,即Optimized Dex。经过预处理后的ODEX文件,在运行时会比.dex文件在速度上快很多。但是,在早期的Android系统中,DexOpt有一个bug,它在执行时会把每一个类的方法id检索出来,存在一个链表结构中。这个链表的长度使用short类型保存的,这也就导致了方法的数目不能够超过65536个。这里的方法除了应用程序写的方法,还有第三方库中的方法,本地的方法。当一个项目的体积足够庞大时,这个方法数目的上限是不能满足需求的。在Andorid5.0之后,Android使用了ART(Android RunTime)来代替Dalvik虚拟机。ART本身就支持多dex的apk。它将多个dex文件组装成oat文件再运行。
ART与Dalvik的区别。
尽管Android在新版本中解决了这个问题,但是为了兼容低版本,我们还是要学习Android的dex分包。QQ空间的热修复技术也是基于dex分包实现的。
下面介绍一下如何在gradle中实现dex分包
首先在module的build.gradle文件的dependencies模块中添加如下语句,加载multidex包:
compile 'com.android.support:multidex:1.0.0'然后在defaultConfig中添加注释处的语句,设置mutiDex模式:
defaultConfig { applicationId "com.internetplus.yxy.intelligentspace" minSdkVersion 15 targetSdkVersion 25 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" multiDexEnabled true //设置multiDex模式 }
在AndroidManifest.xml文件中定义Application:
<application android:allowBackup="true" android:name=".MyApplication"></application>
MyApplication类继承MultiDexApplication,并在onCreate中注册:
public class MyApplication extends MultiDexApplication {public void onCreate() { super.onCreate(); refWatcher = LeakCanary.install(this); FileDownloader.init(this); MultiDex.install(this);}}或者在AndroidManifest.xml文件中直接使用 android.support.multidex.MultiDexApplication。还可以在MyApplication重写attachBaseContext()方法,并使用上文中的方法进行注册。
这样,最基本的分包就已经完成了,当你的apk方法数大于65536的时候,apk就会自动分包。包的名称为classes.dex(此为主dex包),classes2.dex,classes3.dex ...
如果你想做一些更详细的控制,还可以添加相应的参数,比如指定哪些类放在主dex包中,每个包的方法数上限。在gradle1.5之前,可以在afterEvaluate语句中添加additionalParameters来进行控制:
afterEvaluate { tasks.matching { it.name.startsWith('dex') }.each { dx -> if (dx.additionalParameters == null) { dx.additionalParameters = [] } dx.additionalParameters += '--multi-dex' dx.additionalParameters += '--set-max-idx-number=20000' // 设置每个dex包的最多方法数为20000 }}但在gradle1.5之后,修改了分包的参数api,这样的设置方法已经无法使用了。但在2.2版本中,这些api又开放了,不过要在DexOptions中进行添加设置:dexOptions { preDexLibraries = false additionalParameters = ['--multi-dex', '--set-max-idx-number=20000'] }使用之前记得把jdk升到1.8再使用。
另附一个查看dex包中方法数的方法:建立两个文件:printhex.ps1 , dex-method-count.bat
printhex.ps1:
<#.SYNOPSISOutputs the number of methods in a dex file..PARAMETER PathSpecifies the path to a file. Wildcards are not permitted.#>param( [parameter(Position=0,Mandatory=$TRUE)] [String] $Path)if ( -not (test-path -literalpath $Path) ) { write-error "Path '$Path' not found." -category ObjectNotFound exit}$item = get-item -literalpath $Path -forceif ( -not ($? -and ($item -is [System.IO.FileInfo])) ) { write-error "'$Path' is not a file in the file system." -category InvalidType exit}if ( $item.Length -gt [UInt32]::MaxValue ) { write-error "'$Path' is too large." -category OpenError exit}$stream = [System.IO.File]::OpenRead($item.FullName)$buffer = new-object Byte[] 2$stream.Position = 88$bytesread = $stream.Read($buffer, 0, 2)$output = $buffer[0..1] #("{1:X2} {0:X2}") -f $output$outputdec = $buffer[1]*256 + $buffer[0]"Number of methods is " + $outputdec$stream.Close()dex-method-count.bat:
@ECHO OFFIF "%1"=="" GOTO MissingFileNameErrorIF EXIST "%1" (GOTO ContinueProcessing) ELSE (GOTO FileDoesntExist):ContinueProcessingset FileNameToProcess=%1set FileNameForDx=%~n1.dexIF "%~x1"==".dex" GOTO ProcessWithPowerShellREM preprocess Jar with dxIF "%~x1"==".jar" ( ECHO Processing Jar %FileNameToProcess% with DX! CALL dx --dex --output=%FileNameForDx% %FileNameToProcess% set FileNameToProcess=%FileNameForDx% IF ERRORLEVEL 1 GOTO DxProcessingError):ProcessWithPowerShellECHO Counting methods in DEX file %FileNameToProcess%CALL powershell -noexit -executionpolicy bypass "& ".\printhex.ps1" %FileNameToProcess%GOTO End:MissingFileNameError@ECHO Missing filename for processingGOTO End:DxProcessingError@ECHO Error processing file %1% with dx!GOTO End:FileDoesntExist@ECHO File %1% doesn't exist!GOTO End:End然后将dex包和两个文件放到一个目录里面,打开命令行并切换到当前目录,运行:dex-method-count.bat classes.dex就可以看到dex包内的方法数了。0 0
- Android dex分包方案
- Android dex分包方案
- android dex分包
- Android dex分包方案
- Android dex分包技术
- Android dex分包方案
- Android Dex分包
- Android dex分包方案
- Android dex分包方案
- Android dex分包方案
- Android dex 分包方案
- Android dex分包方案
- Android dex分包方案
- Android dex分包方案
- Android dex分包方案
- Android DEX 分包
- Android中的dex分包
- Android dex分包方案
- Mac下配置tomcat
- Mysql 统计同一字段不同值的个数
- 初识对话框
- 用Python模拟操作系统中的round robin算法
- 【计算机视觉】opencv姿态解算5 OpenGL与OpenCV实现增强现实
- Android dex分包
- Dijkstra算法一个人的旅行 杭电oj
- JavaScript之函数与作用域
- 初识信号与槽
- MySQL入门实践(三)
- eclipse连接hadoop集群
- 同步图计算框架GraphLite编程之图着色
- JavaScript数据图表库推荐--百度ECharts
- 深入理解vector的拷贝构造