Android-Multidex安装流程解析
关于为什么需要引入Multidex支持以及如何配置Multidex可参考官网,本篇不做阐述,本篇着重分析Multidex1.0.2源码进行分析
大家都知道配置Multidex都需要在Application中的添加这样代码
public class MyApplication extends SomeOtherApplication {
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(context);
Multidex.install(this);
}
}
其关键代码是Multidex类的install方法,我们来看看内部如何实现
public final class MultiDex {
static final String TAG = "MultiDex";
private static final Set<File> installedApk = new HashSet();
private static final boolean IS_VM_MULTIDEX_CAPABLE = isVMMultidexCapable(System.getProperty("java.vm.version"));
...
private MultiDex() {
}
public static void install(Context context) {
Log.i("MultiDex", "Installing application");
//1、判断虚拟机是否支持MultiDex
if(IS_VM_MULTIDEX_CAPABLE) {
Log.i("MultiDex", "VM has multidex support, MultiDex support library is disabled.");
} else if(VERSION.SDK_INT < 4) {
//2、Android SDK小于4不支持Multidex
throw new RuntimeException("MultiDex installation failed. SDK " + VERSION.SDK_INT + " is unsupported. Min SDK version is " + 4 + ".");
} else {
try {
ApplicationInfo applicationInfo = getApplicationInfo(context);
if(applicationInfo == null) {
Log.i("MultiDex", "No ApplicationInfo available, i.e. running on a test Context: MultiDex support library is disabled.");
return;
}
//3、关键代码
doInstallation(context, new File(applicationInfo.sourceDir), new File(applicationInfo.dataDir), "secondary-dexes", "");
} catch (Exception var2) {
Log.e("MultiDex", "MultiDex installation failure", var2);
throw new RuntimeException("MultiDex installation failed (" + var2.getMessage() + ").");
}
Log.i("MultiDex", "install done");
}
}
static boolean isVMMultidexCapable(String versionString) {
boolean isMultidexCapable = false;
if(versionString != null) {
Matcher matcher = Pattern.compile("(\\d+)\\.(\\d+)(\\.\\d+)?").matcher(versionString);
if(matcher.matches()) {
try {
int major = Integer.parseInt(matcher.group(1));
int minor = Integer.parseInt(matcher.group(2));
isMultidexCapable = major > 2 || major == 2 && minor >= 1;
} catch (NumberFormatException var5) {
;
}
}
}
Log.i("MultiDex", "VM with version " + versionString + (isMultidexCapable?" has multidex support":" does not have multidex support"));
return isMultidexCapable;
}
}
小结:Multidex.install方法可分为如下3步
1、判断VM是否原生支持Multidex,如果支持就不进行Multidex.install方法
2、如果Android SDK小于4,直接抛出异常提示不支持Multidex
3、也是最关键的代码即doInstallation方法
继续看doInstallation方法
private static void doInstallation(Context mainContext, File sourceApk, File dataDir, String secondaryFolderName, String prefsKeyPrefix) throws IOException, IllegalArgumentException, IllegalAccessException, NoSuchFieldException, InvocationTargetException, NoSuchMethodException {
//installedApk是个全局静态变量Set集合
Set var5 = installedApk;
synchronized(installedApk) {
if(!installedApk.contains(sourceApk)) {
//1、如果集合中不存在将souceApk文件加入其中
installedApk.add(sourceApk);
//Android5.0以及以上版本使用ART机制运行,后者原生支持从 APK 文件加载多个 DEX 文件
if(VERSION.SDK_INT > 20) {
Log.w("MultiDex", "MultiDex is not guaranteed to work in SDK version " + VERSION.SDK_INT + ": SDK version higher than " + 20 + " should be backed by " + "runtime with built-in multidex capabilty but it's not the " + "case here: java.vm.version=\"" + System.getProperty("java.vm.version") + "\"");
}
ClassLoader loader;
try {
//此处获取的类型为PathClassLoader,后面安装非主dex会使用到
loader = mainContext.g