Android插件化原理
2020-06-12 本文已影响0人
Athephoenix
学以致用,但暂时不用不代表不学,知识储备重在平时。
不积跬步,无以至千里。
插件化技术的作用
首先,它的作用是什么,解决什么问题;
其次,实现的方式有那些。
最后,现有的热门框架有那些可以直接使用和学习;
插件化,把功能或者模块抽出来单独处理,减小宿主app的体积。基于此种特性可以实现诸如,热修复,补丁更新等,当然这里只是从实现原理上来归类,并非这些技术之间关系。
已有的主要分为三种实现原理:
- 类加载机制
- InstantRun
- native层method替换
本篇主要带你了解基于类加载机制实现插件化。
基于类加载机制
PathClassLoader 可以加载已经安装的apk文件
DexClassLoader 可以加载任意位置的zip文件
try {
// 1.加载应用程序的dex
PathClassLoader pathLoader = (PathClassLoader) appContext.getClassLoader();
for (File dex : loadedDex) {
// 2.加载指定的修复的dex文件
DexClassLoader dexLoader = new DexClassLoader(
dex.getAbsolutePath(),// 修复好的dex(补丁)所在目录
fopt.getAbsolutePath(),// 存放dex的解压目录(用于jar、zip、apk格式的补丁)
null,// 加载dex时需要的库
pathLoader// 父类加载器
);
// 3.合并
Object dexPathList = getPathList(dexLoader);
Object pathPathList = getPathList(pathLoader);
Object leftDexElements = getDexElements(dexPathList);
Object rightDexElements = getDexElements(pathPathList);
// 合并完成
Object dexElements = combineArray(leftDexElements, rightDexElements);
// 重写给PathList里面的Element[] dexElements;赋值
Object pathList = getPathList(pathLoader);// 一定要重新获取,不要用pathPathList,会报错
setField(pathList, pathList.getClass(), "dexElements", dexElements);
}
} catch (Exception e) {
e.printStackTrace();
}
通过解析zip(可能包含dex,jar,aar等)文件获得dex文件,并且将其和加入Element[]数组,并和app本身的element数组合并,然后通过反射将合并后的结果赋值给app实际使用的pathLoader。
基于Android虚拟机的运行状态,会在需要使用时,从内存中查找class,使用更新后的功能,进而完成我们的需求。那么为什么从内存中能查找到我们更新后的lclass,而不是之前的class呢。
首先,已经将更新后的包含class文件的dex文件插在Element[]
首位,其次,classLoader类在设计时遵循双亲委派/可见性/唯一性原则,简单的理解从首个dex文件中查找到更新后的class文件之后,则停止,不再查找后面原来的class。