版本
v0.6.5
温馨提示
配合 推荐 Matrix 源码完整注释
可能会有更好的效果
概述
本篇文章是 腾讯开源的 APM 框架 Matrix 系列文章的第二篇,将对 matrix-android-lib
这个模块的代码进行阅读。这个模块主要是对Matrix 插件架构进行构建。上一篇为Matrix 源码阅读 - gradle插件
先看一下类图及类功能的简介。
- Matrix:Matrix整个框架运行期的入口。也控制着插件的生命周期。所有插件都需要注册到Matrix这个类中进行统一管理
- AppActiveMatrixDelegate:相当于Application的代理,本身可以感知Activity生命周期,和 APP 进入前台还是 退出到后台 ,感知到以后 会通知给
IAppForeground
- IPlugin:定义了所有 Plugin的生命周期及通用方法
- IssuePublisher.OnIssueDetectListener:只有一个
onDetectIssue
方法,当需要上报问题时会被调用 - IAppForeground: 只有一个方法就是
onForeground
会被AppActiveMatrixDelegate
调用,可以感知 APP 进入前台还是 退出到后台 - Plugin: 实现了
IPlugin
,ssuePublisher.OnIssueDetectListener
和IAppForeground
。是所有插件的父类,本身兼具插件的 生命周期,感知 问题和 APP状态切换的功能。具体实现有TracePlugin
,IOCanaryPlugin
,ResourcePlugin
,SQLiteLintPlugin
后面我们会挨个分析。
下面我们就从 Matrix这个入口类开始看。
1. Matrix
我们使用Matrix一般会这样初始化
Matrix.Builder builder = new Matrix.Builder(this);
builder.plugin(new TracePlugin());
builder.plugin(new IOCanaryPlugin());
.....
//详见【1.1】
Matrix matrix=builder.build();
//详见【3.1】
matrix.startAllPlugins();
1.1 Matrix构造方法
看到builder 就知道是使用建造者模式来创建Matrix对象,所以我们二话不说直接看Matrix的构造方法
private Matrix(Application app, PluginListener listener, HashSet<Plugin> plugins) {
//保存builder传入的参数
this.application = app;
this.pluginListener = listener;
this.plugins = plugins;
//初始化Application的代理对象 详见【1.2】
AppActiveMatrixDelegate.INSTANCE.init(application);
for (Plugin plugin : plugins) {
//调用plugin的init方法 详见【2.1】
plugin.init(application, pluginListener);
//回调plugin onInit生命周期
pluginListener.onInit(plugin);
}
}
可以看到Matrix的构造方法中,做了三件事
- 首先是将builder中传入的参数保存到自己的成员变量中,其中最重要的就是HashSet中存储的各个
Plugin
. - 初始化
AppActiveMatrixDelegate
这个Application的代理对象 - 循环调用所有
Plugin
的init方法
1.2 AppActiveMatrixDelegate.init()
值得说一下的是 AppActiveMatrixDelegate
这个类是个 枚举单例,不了解枚举单例好处及和其他几种单例方式区别的同学,可以自行百度,谷歌一下,网上文章一大把。
我们继续看AppActiveMatrixDelegate.init()
//详见【1.3】
Controller controller = new Controller();
public void init(Application application) {
//保证只初始化一次
if (isInit) {
return;
}
this.isInit = true;
//获取 子线程 handler
this.handler = new Handler(MatrixHandlerThread.getDefaultHandlerThread().getLooper());
//监听 onConfigurationChanged 和 onLowMemory
application.registerComponentCallbacks(controller);
//监听activity生命周期
application.registerActivityLifecycleCallbacks(controller);
}
可以看到在init()
方法中, application注册了ActivityLifecycleCallbacks
和ComponentCallbacks2
这两个监听,并且这两个监听指向了同一个对象Controller
.有了这两个监听ActivityLifecycleCallbacks
就具有了 感知Activity生命周期和APP活动的能力。
1.3 Controller
private final class Controller implements Application.ActivityLifecycleCallbacks, ComponentCallbacks2 {
@Override
public void onActivityStarted(Activity activity) {
//更新当前页面名称 详见【1.4】
updateScene(activity);
//广播 APP切换到前台的 事件 详见【1.5】
onDispatchForeground(getVisibleScene());
}
@Override
public void onActivityStopped(Activity activity) {
if (getTopActivityName() == null) {
//广播 APP切换到后台的 事件 详见【1.6】
onDispatchBackground(getVisibleScene());
}
}
.....
@Override
public void onTrimMemory(int level) {
MatrixLog.i(TAG, "[onTrimMemory] level:%s", level);
if (level == TRIM_MEMORY_UI_HIDDEN && isAppForeground) { // fallback
//广播 APP切换到后台的 事件
onDispatchBackground(visibleScene);
}
}
}
可以看到Controller
是真正感知APP状态的类。
1.4 Controller .updateScene()
private void updateScene(Activity activity) {
//记录当前activity的名称
visibleScene = activity.getClass().getName();
}
1.5 Controller .onDispatchForeground()
private void onDispatchForeground(String visibleScene) {
//如果APP已经是可见的,就不做任何操作
if (isAppForeground || !isInit) {
return;
}
handler.post(new Runnable() {
@Override
public void run() {
//修改APP状态为可见
isAppForeground = true;
synchronized (listeners) {
for (IAppForeground listener : listeners) {
//通知给各个监听者
listener.onForeground(true);
}
}
}
});
}
1.6 Controller .onDispatchBackground()
private void onDispatchBackground(String visibleScene) {
//如果APP已经是不可见的,就不做任何操作
if (!isAppForeground || !isInit) {
return;
}
handler.post(new Runnable() {
@Override
public void run() {
isAppForeground = false;
synchronized (listeners) {
for (IAppForeground listener : listeners) {
//通知给各个监听者
listener.onForeground(false);
}
}
}
});
}
2.1Plugin.init()
Matrix
的构造方法中AppActiveMatrixDelegate
对象初始化完成后就调用了Plugin.init()
方法
@Override
public void init(Application app, PluginListener listener) {
....
//将plugin当前的状态切换到 PLUGIN_INITED
status = PLUGIN_INITED;
this.application = app;
this.pluginListener = listener;
//将自己注册到 AppActiveMatrixDelegate 中 详见【2.2】
AppActiveMatrixDelegate.INSTANCE.addListener(this);
}
2.2 AppActiveMatrixDelegate.INSTANCE.addListener(this);
可以看到Plugin
在init的时候将自己注册到了AppActiveMatrixDelegate
中,当APP前后台状态改变是 Plugin就能感知到
public void addListener(IAppForeground listener) {
synchronized (listeners) {
//添加监听器
listeners.add(listener);
}
}
3.1 Matrix.startAllPlugins()
startAllPlugins
这个方法比较简单就是启动所有的插件,Matrix作为插件的管理者理还具有其他类似的方法如 stopAllPlugins
,destroyAllPlugins
//启动所有插件
public void startAllPlugins() {
for (Plugin plugin : plugins) {
plugin.start();
}
}
Plugin.onDetectIssue()
//组织 问题的 Json数据 并调用 监听的 onReportIssue 方法
@Override
public void onDetectIssue(Issue issue) {
if (issue.getTag() == null) {
// set default tag
issue.setTag(getTag());
}
issue.setPlugin(this);
JSONObject content = issue.getContent();
// add tag and type for default
try {
if (issue.getTag() != null) {
content.put(Issue.ISSUE_REPORT_TAG, issue.getTag());
}
if (issue.getType() != 0) {
content.put(Issue.ISSUE_REPORT_TYPE, issue.getType());
}
content.put(Issue.ISSUE_REPORT_PROCESS, MatrixUtil.getProcessName(application));
content.put(Issue.ISSUE_REPORT_TIME, System.currentTimeMillis());
} catch (JSONException e) {
MatrixLog.e(TAG, "json error", e);
}
//MatrixLog.e(TAG, "detect issue:%s", issue);
pluginListener.onReportIssue(issue);
}
Plugin
提供了简单的统一的数据上报方法,并对上报数据封装成统一格式的Json字符串。
总结:
-
Matrix
是整个框架的入口也是所有插件的管理者 - 所有的插件都需要继承
Plugin
,Plugin
本身已经具备了 问题上报和感知APP前后台状态的能力。
系列文章
- 腾讯 Apm 框架 Matrix 源码阅读 - gradle插件
- 腾讯 Apm 框架 Matrix 源码阅读 - 架构解析
- 腾讯 Apm 框架 Matrix 源码阅读 - TracePlugin 架构解析
- 腾讯 Apm 框架 Matrix 源码阅读 - TracePlugin 之 FrameTracer
- 腾讯 Apm 框架 Matrix 源码阅读 - TracePlugin 之 StartupTracer
- 腾讯 Apm 框架 Matrix 源码阅读 - TracePlugin 之 AnrTracer
- 腾讯 Apm 框架 Matrix 源码阅读 - TracePlugin 之 上报字段含义