推荐使用AS,只需要在gradle中进行配置和添加一些代码即可实现分包
Multidex实现及原理
1. 什么是分包?分包可以解决什么问题?
分包(multidex)是指apk文件中含有多于一个classes.dex的dex文件,如classes2.dex。
下面是我的一个私人项目,我们在AndroidStudio中,对该项目APK进行分析,获得该apk下的目录结构如图:
我们可以看到上面的apk目录结构中有且仅有一个classex.dex文件。
- classes.dex:代码文件
- res:资源
- lib:存放so库文件
- resources.arsc:资源的索引,相对于R目录,(上面的目录结构中没有)
- META-INF:签名信息
- AndroidManifest.xml:清单文件
- assets:资源文件(无ID)
再来看下我反编译的某应用下目录结构:
可以看到除了classes.dex外还有一个classes2.dex。
了解了什么是分包后,再来思考为啥要在自己的项目中去费力的多分一个.dex文件。不分不行吗?还真就得分。
在Android 5.0以前使用的是dalvik虚拟机,dalvik虚拟机中使用了一个short字段来保存一个dex方法数,最大不能超过65535。倘若我们的应用越来越大,方法数也是越来越多,为了程序不发生ANR等就势必要采用分包来减少classes.dex中的方法数。
2. Java中Classloader机制介绍
2.1 Java中常见的类加载器:
(1)BootstrapClassLoader:纯C++实现的类加载器,没有对应的Java类,主要加载jre/lib/目录下的核心库
(2) ExtClassLoader:类全名是sun.misc.Launcher$ExtClassLoader,主要加载/jre/lib/ext/目录下的扩展包
(3)AppClassLoader:sun.misc.Launcher$AppClassLoader,主要加载CLASSPATH路径下的包
2.2 一个类加载器如何加载一个类
加载一个类的过程:工程中的类被AppClassLoader加载,首先会委托给它的父加载器ExtClassLoader去加载,同样的,ExtClassLoader会委托给它的父加载器去加载,但是ExtClassLoader是没有父加载器的,所以委托给了BootstrapClassLoader,(BootstrapClassLoader为最顶级的ClassLoader),它会直接去加载:%java_home%/jre/lib路径下的,如果加载成功就返回ExtClassLoader,ExtClassLoader再返回到AppClassLoader,一个类的加载到此结束。如果BootstrapClassLoader加载失败,需要ExtClassLoader自己利用findClass(name)到路径:%java_home%/jre/lib/ext目录下去加载,如果加载成功返回给AppClassLoader,如果加载失败,就需要AppClassLoader自己利用findClass(name)到路径:CLASSPATH下去加载。这就是父委托机制的加载流程。
2.3 父委托加载机制的好处
可以提高软件系统的安全性。
3. Android中常用的类加载器
- PathClassLoader: 加载/data/app目录下apk文件,PathClassLoader主要用来加载已经安装好了的apk。
- DexClassLoader: 加载路径需要在创建DexClassLoader时传入,可以加载任何路径下的apk/dex/jar。(可以加载没有被安装好的apk文件)
4. 两种分包方案原理介绍和动态加载
4.1 Ant实现方式
(由于ant主要是与eclipse来配合使用的,所以感兴趣的可以自行百度或谷歌)
4.2 Gradle实现分包的原理及过程
谷歌对于分包:http://developer.android.com/tools/building/multidex.html
Gradle分包的步骤:
第一步添加:multiDexEnabled true
android {
...
defaultConfig {
...
//Enabling multidex support
multiDexEnabled true
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
第二步添加:compile'com.android.support:multidex:1.0.0'
dependencies {
compile'com.android.support:multidex:1.0.0'
}
第三步执行:
public class MyApplication extends MultiDexApplication{
@Override
public void onCreate(){
}
}
//或者
public void onCreate(Bundle arguments){
MultiDex.install(getTargetContext());
super.onCreate(arguments);
}
(适用于项目中有自定义Application情况)。
4.3 分包注意事项
Gradle分包的优缺点:
优点
- 使用简单
- 分Dex可以进行混淆
缺点
- 无法手动制定哪些类放入分Dex
android{
//...
dexOptions{
javaMaxHeapSize"2g"
}
}