Android 插件化框架经过多年的发展已经出现很多成熟的方案。依然记得自己最早接触的DL框架,在能够让APP不经过安装就可以加载功能新模块,别提有多兴奋。再到之后的360的 DroidPlugin 等等,感谢开发者们无私的奉献,让大家受益匪浅。
接下来会有一个插件化系列的文章主要介绍一下当下一些插件化框架的设计思想和代码逻辑,深入理解插件化开发。
Replugin 框架原理
Replugin 框架是360开源的一款插件化框架,其实现思路走的还是占坑的思想,我们知道Android的组件需要在AndroidManifest.xml中注册,占坑的思想就是预先注册坑位,然后用插件中的组件替换坑位注册的组件欺骗系统从而实现组件的加载,这个和360 张勇的DroidPlugin思想是一样的,两者的一大区别就是 Replugin 宣传的唯一 hook点。只 hook了系统的ClassLoader。而DroidPlugin则几乎是完全自己实现了一套Framework层中对Service和Activity加载的方案,替换掉了系统几乎全部相关的Binder
。 这样的话Replugin的系统侵入性更低,维护成本更低,问题更少更加稳定。
Replugin为了实现插件的管理会开启一个常驻进程作为service 端,其他插件进程都是client 端,而service端管理着所有插件的 安装,卸载,更新,状态等等功能,当插件进程client 需要实现(安装,卸载,更新,状态等等)这些功能的时候是通过进程间通信Binder机制实现的。这样的思想和Android 系统的 AMS有点类似。
Replugin框架的注册
Replugin中有一个RepluginApplication类直接继承这个类就可以实现框架的注册,也可以在自己Application类中回调的方法中调用相关方法,首先要调用的就是attachBaseContext()方法,要在这个方法中完成框架的初始化。
//com.qihoo360.replugin.RePlugin
public static void attachBaseContext(Application app, RePluginConfig config) {
//初始化一次
if (sAttached) {
return;
}
//这个类主要缓存application对象
RePluginInternal.init(app);
sConfig = config;
//初始化默认值
sConfig.initDefaults(app);
IPC.init(app);
// 初始化HostConfigHelper(通过反射HostConfig来实现)
// NOTE 一定要在IPC类初始化之后才使用
HostConfigHelper.init();
// FIXME 此处需要优化掉
AppVar.sAppContext = app;
//PluginStatusController用来管理插件的运行状态:
//用来管理插件的状态:正常运行、被禁用,等情况
//设置Application的引用
PluginStatusController.setAppContext(app);
PMF.init(app);
PMF.callAttach();
sAttached = true;
}
一 . 第一个要要讲一下的是 sConfig.initDefaults(app);
//com.qihoo360.replugin.RePluginConfig
void initDefaults(Context context) {
if (pnInstallDir == null) {
pnInstallDir = context.getFilesDir();
}
if (callbacks == null) {
callbacks = new RePluginCallbacks(context);
}
if (eventCallbacks == null) {
eventCallbacks = new RePluginEventCallbacks(context);
}
}
1.获取pn插件安装目录
2.创建RePluginCallbacks
3.创建RePluginEventCallbacks
首先RePluginCallbacks 这个类很重要主要用来生成宿主和插件的ClassLoader,是插件化的关键,这个类中还有相关的回调。下图是主要的几个方法。
RePluginEventCallbacks:插件化框架对外事件回调接口集,宿主需继承此类,并复写相应的方法来自定义插件框架的事件处理机制,其中有安装插件成功、失败、启动插件Activity时的一些事件回调等。我们可以重写这些方法然后再相应的回调中做相应的操作,比如插件安装失败弹出提示框等。
二,接下来是IPC.init(app);
//com