Android插件化原理

学以致用,但暂时不用不代表不学,知识储备重在平时。
不积跬步,无以至千里。

插件化技术的作用

首先,它的作用是什么,解决什么问题;
其次,实现的方式有那些。
最后,现有的热门框架有那些可以直接使用和学习;

插件化,把功能或者模块抽出来单独处理,减小宿主app的体积。基于此种特性可以实现诸如,热修复,补丁更新等,当然这里只是从实现原理上来归类,并非这些技术之间关系。

已有的主要分为三种实现原理:

  1. 类加载机制
  2. InstantRun
  3. 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。

参考:
https://juejin.im/post/5a0ad2b551882531ba1077a2

你可能感兴趣的:(Android插件化原理)