插件化实现基础

自定义插件化:

 


插件化对Manifest处理主要核心是有两个工作:第一个工作是文件的合并,就是文件的io操作,将所有的清单文件合并到总的manifest里面去。第二个点就比较复杂了:需要修改整个构建流程,这样的话新的构建流程才能将所有的插件中清单文件合并到数组manifest文件中。

插件化框架如果加载插件当中的类:

我们每一个插件都是一个apk,既然是apk 那么它里面就有自己的dex文件,所有的class字节码就都存储在dex文件中,当前市面上的插件化框架基本都是这样去加载插件中的类的,首先它会区分宿主apk,和各个插件apk的。为什么要区分呢由于我们的宿主apk已经安装到了系统中,所以Android系统会给宿主apk去创建它自己的classLoader,而无需手动去创建,所以我们宿主apk中的classLoader,有pathClassLoader就够用了,这是我们的宿主apk文件。那么我们的各个插件apk呢,由于各个业务插件apk并没有安装到我们的系统中,所以各个插件apk本身它是没有classLoader的,也就是Android系统不会为这些没有安装过的apk文件去创建classLoader,而要想加载创建中的apk文件,又必须要有classLoader,那么这时候就该我们插件化框架出马,创建话框架它会给每个插件去创建对应的classLoader,这样的话在加载每个插件中的apk文件的时候,它会使用为每个插件创建的classLoader去加载对应插件中的class文件,也就是BundleClassLoader的父对象为BootClassLoader,并且这个BootClassLoader中包含PathClassLoader对象,这样的话在数组没有加载过这个类的时候,就调用插件化跟他注入自己的BundleClassLoader去完成类的加载,所以我们的宿主Bundle(创建)和我们的业务Bundle是要分别对待的。宿主Bundle核心就是系统帮他创建好了自己的classLoader,而且是pathClassLoader;而各个插件并没有安装,所以是由我们的插件化框架为我们插件对应的classLoader去完成类的加载。

那么这就涉及两个问题:

 

插件化实现简单流程:


1、初始化DexClassLoader,在new 出DexClassLoader的时候需要传入四个参数,第一个:要加载apk文件路径;第二个参数:插件apk要解压到哪个路径当中(这个路径必须是宿主apk的内部文件);第三个参数:查找的关联路径,一般传入null即可;第四个参数:当前classLoader的父classLoader。

2、有了这个classLoader以后就可以去加载这个apk中所有的类文件了,既然要加载就需要调用classLoader的loadClass方法,传入我们插件apk中的类文件名,然后去获取对应的字节码。

3、如果我们找到了它的字节码,那么我们就可以通过反射去创建这个对象,然后调用它的方法。

自定义classLoader:(核心基本原理)


1)写一个类使之继承dexclassLoader

2)实现该类的构造方法

3)重写findClass方法。定义了我们这个classLoader要以何种策略加载我们的class文件。得到classLoader的二进制字节数组,把字节数组转化class对应的字节码(通过文件流去获取我们的字节码)。    通过指定路径完成class字节码的加载,以及最后通过获取到的字节码将转化为class对象。

插件资源文件的加载:


安装的apk获取资源:如果这个资源只有文件名,那么我们就需要通过AssetManager去直接根据文件名去加载这个资源。而这个资源有对应的ID,比如说图片、布局、动画等等是会生成resource ID的,这个时候我们就可以通过resource这个类来完成对应资源文件的加载,加载完以后最后再通过AssetManager这个类去完成资源文件的读写。所以归根结底我们资源文件读取操作都是通过AssetManager这个类来完成的,而resource这个类说到底就是完成一个由资源ID到资源文件名的一个映射。核心还是我们的AssetManager,有了AssetManager以后,我们的一个APK中所有的资源都可以去加载。


具体实现:

 


通过反射去获取AssetManager类,得到它的实例,再拿到它的addAssetPath方法,拿到这个方法以后,调用它的invoke方法传入AssetManager对象,和参数apkPath。

 

先得到AssetManager对象,然后先拿到宿主apk 的resource,再直接new 出一个Resource,传入三个参数(AssetManager,superResources.getDisplayMetrics(),superResources.getConfiguration()配置);

 


发布了36 篇原创文章 · 获赞 19 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/j18874964028sss/article/details/78534466