插件化开发,dex分包,热修复(Tinker)的思考(二)"/>
关于 Android中的插件化开发,dex分包,热修复(Tinker)的思考(二)
插件化开发的主要原理就是动态加载技术。上文已经对动态加载DexClassLoader进行了解析今天要讲的是动态加载技术的亲戚 —— MultiDex。他们的核心原理之一都是dex文件的加载。
先来理解概念
MultiDex
MultiDex是Google为了解决“65535方法数超标”以及“INSTALL_FAILED_DEXOPT”问题而开发的一个Support库 这篇博客主要是配合源码分析MultiDex的工作原理,使用方法,以及提供一些MultiDex优化的方案。
实现:
1、通过反射获取PathClassLoader中的DexPathList中的Element数组(已加载了第一个dex包,由系统加载)
2、通过反射获取DexClassLoader中的DexPathList中的Element数组(将第二个dex包加载进去)
3、将两个Element数组合并之后,再将其赋值给PathClassLoader的Element数组
谷歌提供的MultiDex支持库就是按照这个思路来实现的。下面看具体原理。
前言:Dex的工作机制
Android程序的每一个Class都是由ClassLoader#loadClass方法加载进内存的,更准确来说,一个ClassLoader实例会有一个或者多个DexFile实例,调用了ClassLoader#loadClass之后,ClassLoader会通过类名,在自己的DexFile数组里面查找有没有那个DexFile对象里面存在这个类,如果都没有就抛ClassNotFound异常。ClassLoader通过调用DexFile的一个叫defineClass的Native方法去加载指定的类,这点与JVM略有不同,后者是直接调用ClassLoader#defineCLass方法,反正最后实际加载类的方法都叫defineClass就没错了。
我们知道ClassLoader主要是通过DexFile.loadDex这个静态方法来创建它需要的DexFile实例的,这里创建DexFile的时候,保存了Dex文件的文件路径mFileName,同时调用了openDexFile的Native方法打开Dex文件并返回了一个mCookie的整型变量(我不知道这个干啥用的,我猜它是一个C++用的资源句柄,用于Native层访问具体的Dex文件)。在Native层的openDexFile方法里,主要做了检查当前创建来的Dex文件是否是有效的Dex文件,还是是一个带有Dex文件的压缩包,还是一个无效的Dex文件。
加载Dex文件里的类
加载类的时候,ClassLoader又是通过DexFile#loadClass这个方法来完成的,这个方法里调用了defineClass这个Native方法,看来DexFile才是加载Class的具体API,加载Dex文件和加载具体Class都是通过Native方法完成,ClassLoader有点名不副实。
MultiDex的工作机制
当一个Dex文件太肥的时候(方法数目太多、文件太大),在打包Apk文件的时候就会出问题,就算打包的时候不出问题,在Android 5.0以下设备上安装或运行Apk也会出问题。既然一个Dex文件不行的话,那就把这个硕大的Dex文件拆分成若干个小的Dex文件,刚好一个ClassLoader可以有多个DexFile,这就是MultiDex的基本设计思路。
使用dx进行拆包
这里还有两个两类:一个是自动拆包,一个手动拆包
–multi-dex:多 dex 打包的开关
–main-dex-list=:参数是一个类列表的文件,在该文件中的类会被打包在第一个 dex 中
–minimal-main-dex:只有在–main-dex-list 文件中指定的类被打包在第一个 dex,其余的都在第二个 dex 文件中
打包过程中如何产生多个的DEX包?
如果做到动态加载,怎么决定哪些DEX动态加载呢?
如果启动后在工作线程中做动态加载,如果没有加载完而用户进行页面操作需要使用到动态加载DEX中的class怎么办?
以上疑问,下方链接有解释。
.html
.html
工作流程
MultiDex的工作流程具体分为两个部分,一个部分是打包构建Apk的时候,将Dex文件拆分成若干个小的Dex文件,这个Android Studio已经帮我们做了(设置 “multiDexEnabled true”),另一部分就是在启动Apk的时候,同时加载多个Dex文件(具体是加载Dex文件优化后的Odex文件,不过文件名还是.dex),这一部分工作从Android 5.0开始系统已经帮我们做了,但是在Android 5.0以前还是需要通过MultiDex Support库来支持(MultiDex.install(Context))。
注意:就是Android中在分包之后会有多个dex,但是系统默认会先找到classes.dex文件然后自动加载运行,所以这里就有一个问题,我们需要将一些初始化的重要类放到classes.dex中,不然运行就会报错或者闪退。
首先来看看使用:
1、修改Gradle的配置,支持multidex:
android {compileSdkVersion <
更多推荐
关于 Android中的插件化开发,dex分包,热修复(Tinker)的思考(二)
发布评论