Android动态加载技术BaseCore

以下是个人在做动态加载技术和阅读插件化源码时,发现的一些大家都会碰到的核心问题。其实不同的插件化方案各有各的特色,但是它们都必须要解决三个基础性问题:
资源访问?、Activity生命周期的管理?和ClassLoader的管理?

1.插件ClassLoader的管理:
对多插件支持,合理管理各个dexclassloader,同一个插件就可以采用同一个classloader去加载类,怎么避免多个classloader家在同一个类时所引发的类型转换错误?

解决:将不同插件的classloader存储在一个hashmap中,这样就可以保证不同插件中的类批次互不干扰!!!

Android动态加载技术BaseCore_第1张图片
5B6FF3C057A9AFAE8C09B41853A45BE9.jpg

2.activity生命周期管理
反射方式很好理解,首先通过Java的反射去获取 Activity的各种生命周期方法,比如onCreate、onStart、onResume等,然后在代理Activity中去调用插件 Activity对应的生命周期方法即可,如下所示。

Android动态加载技术BaseCore_第2张图片
C46CCD4A0A7B4B5A1A14D012F91BA2C0.jpg

缺点:复杂,过多反射性能开销。

接口方式 将Activity的生命周期方法提取出来作为一个接口(DLPlugin)。通过代理activity去调用插件activity的生命周期方法。

Android动态加载技术BaseCore_第3张图片
Paste_Image.png

定义一个接口DLPlugin,把activity生命周期的方法写入。然后,代理的activity调用插件activity的生命周期。


Android动态加载技术BaseCore_第4张图片
8EA7B9BF1F387E65E43F46B36BB9E4D5.jpg

对插件Activity生命周期的管理思想,其中mRemoteActivity就是DLPlugin的实现。

3.资源访问:
宿主和插件的概念?
宿主是指普通的apk,而插件一般是指经过处理的dex或者apk,在主流的插件化框架中多采用经过特殊处 理的apk来作为插件,处理方式往往和编译以及打包环节有关,另外很多插件化框架都需要用到代理Activity的概念,插件Activity的启动大多 数是借助一个代理Activity来实现的。
宿主程序调起未安装的插件apk,一个很大的问题就是资源如何访问,具体来说就是插件中凡是以R开头的资源都不能访问了。这是因为宿主程序中并没有插件的资源,所以通过R来加载插件的资源是行不通的,程序会抛出异常:无法找到某某id所对应的资源!!
插件化的目的就是要减小宿主程序apk包的大小,同时降低宿主程序的更新频率并做到自由装载模块
Activity的工作主要是通过ContextImpl来完成的, Activity中有一个叫mBase的成员变量,它的类型就是ContextImpl。注意到Context中有如下两个抽象方法,看起来是和资源有关 的,实际上Context就是通过它们来获取资源的。这两个抽象方法的真正实现在ContextImpl中,也就是说,只要实现这两个方法,就可以解决资源问题了。

Android动态加载技术BaseCore_第5张图片
Paste_Image.png

具体的实现方式,首先要加载apk中的资源,如下所示

Android动态加载技术BaseCore_第6张图片
Paste_Image.png

从loadResources()的实现可以看出,加载资源的方法是通过反射,通过调用AssetManager中的addAssetPath方 法,我们可以将一个apk中的资源加载到Resources对象中,由于addAssetPath是隐藏API我们无法直接调用,所以只能通过反射。下面 是它的声明,通过注释我们可以看出,传递的路径可以是zip文件也可以是一个资源目录,而apk就是一个zip,所以直接将apk的路径传给它,资源就加 载到AssetManager中了。然后再通过AssetManager来创建一个新的Resources对象,通过这个对象我们就可以访问插件apk中 的资源了,这样一来问题就解决了

Android动态加载技术BaseCore_第7张图片
Paste_Image.png

接着在代理activity获取getasset(),get resources()方法,R的资源文件就可以来访问插件中的资源了。

Android动态加载技术BaseCore_第8张图片
Paste_Image.png

你可能感兴趣的:(Android动态加载技术BaseCore)