一、背景
Matrix-android 当前监控范围包括:应用安装包大小,帧率变化,启动耗时,卡顿,慢方法,SQLite 操作优化,文件读写,内存泄漏等等。
而Trace-Canary包含:帧率fps、启动耗时、卡顿、ANR四个部分。
由于matrix整个系统非常的庞大,所以尽量分开去解读。以免造成心里压力~
二、从初始化流程入手
首先从matrix使用的初始化流程说起。重点关注注释中标注的数字。
// Switch.
DynamicConfigImplDemo dynamicConfig = new DynamicConfigImplDemo();
sContext = this;
MatrixLog.i(TAG, "Start Matrix configurations.");
// 1,Builder.不是必须的,有些插件可以单独配置
Matrix.Builder builder = new Matrix.Builder(this);
// Reporter. Matrix will callback this listener when found issue then emitting it.
// 2,注册plugin监听:包含生命周期如init、start、stop、destroy,还有检测到问题的时候的
onReportIssue回调。
builder.pluginListener(new TestPluginListener(this));
// 3, Configure trace canary.
TracePlugin tracePlugin = configureTracePlugin(dynamicConfig);
builder.plugin(tracePlugin);
//...当然,还有其他插件,后续分析~~ 挖坑 ,哈哈哈
//4, build的时候就创建各种plugin,里面调用了plugin的init方法。
Matrix.init(builder.build());
// 5,Trace Plugin 需要主动调用start()
tracePlugin.start();
MatrixLog.i(TAG, "Matrix configurations done.");
简要分析:
- 构建
Matrix.Builder
,用来注册需要的插件。 Builder不是必须的,可以单独初始化某个plugin - 注册plugin的生命周期回调:
init()
、start()
、stop()
、destroy()
,以及检测到问题后的回调:(onReportIssue(Issue issue)
) - 调用
configureTracePlugin()
方法构建tracePlugin
对象返回,注册 - 调动
build()
生成matrix
对象,里面会调用所有已注册的plugin的init
方法 - tracePlugin 调用
start()
方法
2.1 configureTracePlugin()方法
private TracePlugin configureTracePlugin(DynamicConfigImplDemo dynamicConfig) {
//配置开关
boolean fpsEnable = dynamicConfig.isFPSEnable();
boolean traceEnable = dynamicConfig.isTraceEnable();
boolean signalAnrTraceEnable = dynamicConfig.isSignalAnrTraceEnable();
File traceFileDir = new File(getApplicationContext().getFilesDir(), "matrix_trace");
if (!traceFileDir.exists()) {
if (traceFileDir.mkdirs()) {
MatrixLog.e(TAG, "failed to create traceFileDir");
}
}
//创建anr文件夹用来存储anr文件
File anrTraceFile = new File(traceFileDir, "anr_trace"); // path : /data/user/0/sample.tencent.matrix/files/matrix_trace/anr_trace
// 创建日志print的文件夹 ??
File printTraceFile = new File(traceFileDir, "print_trace"); // path : /data/user/0/sample.tencent.matrix/files/matrix_trace/print_trace
TraceConfig traceConfig = new TraceConfig.Builder()
.dynamicConfig(dynamicConfig)
.enableFPS(fpsEnable)
.enableEvilMethodTrace(traceEnable)
// anr?
.enableAnrTrace(traceEnable)
.enableStartup(traceEnable)
.enableIdleHandlerTrace(traceEnable) // Introduced in Matrix 2.0 ,新引入的idleHandler监控
.enableMainThreadPriorityTrace(true) // Introduced in Matrix 2.0 新引入的主线程优先级监控
.enableSignalAnrTrace(signalAnrTraceEnable) // Introduced in Matrix 2.0 新引入的信号anr监控, native anr??
.anrTracePath(anrTraceFile.getAbsolutePath())
.printTracePath(printTraceFile.getAbsolutePath())
.splashActivities("sample.tencent.matrix.SplashActivity;") //??
.isDebug(true)
.isDevEnv(false)
.build();
//Another way to use SignalAnrTracer separately
//useSignalAnrTraceAlone(anrTraceFile.getAbsolutePath(), printTraceFile.getAbsolutePath());
// 返回对象
return new TracePlugin(traceConfig);
}
主要工作就是配置tracePlugin的各种功能,可以根据自身项目的需要进行取舍。
2.2 Matrix.Build的build()方法
build()方法最终会创建matrix对象。
public Matrix build() {
if (pluginListener == null) {
pluginListener = new DefaultPluginListener(application);
}
return new Matrix(application, pluginListener, plugins);
}
private Matrix(Application app, PluginListener listener, HashSet<Plugin> plugins) {
this.application = app;
this.pluginListener = listener;
this.plugins = plugins;
//1,AppActiveMatrixDelegate是一个枚举类,注册了activity回调和onLowMemory回调
AppActiveMatrixDelegate.INSTANCE.init(application);
// 2,调用插件的init的方法
for (Plugin plugin : plugins) {
plugin.init(application, pluginListener);
//通知pluginListener,初始化完成
pluginListener.onInit(plugin);
}
}
2.2.1 AppActiveMatrixDelegate.init(Application application)
两个作用:
- 注册registerComponentCallbacks 回调,目的是监听系统的onTrimMemory回调
- 注册activity生命周期回调,目的是维护一个前后台的状态
public void init(Application application) {
if (isInit) {
MatrixLog.e(TAG, "has inited!");
return;
}
this.isInit = true;
if (null != MatrixHandlerThread.getDefaultHandlerThread()) {
this.handler = new Handler(MatrixHandlerThread.getDefaultHandlerThread().getLooper());
}
application.registerComponentCallbacks(controller);
application.registerActivityLifecycleCallbacks(controller);
}
registerActivityLifecycleCallbacks()
作用:
管理和维护App前后台状态,并通过 onDispatchForeground()
中回调接口IAppForeground
的onForeground(boolean isForeground)
方法,因为plugin都实现了这个接口,因此每个plugin都能感知到前后台状态切换。
需要注意的是该回调是在子线程中,线程名字为default_matrix_thread。这个线程是matrix的工作线程,由MatrixHandlerThread
类来管理。
@Override
public void onActivityStarted(Activity activity) {
updateScene(activity);
onDispatchForeground(getVisibleScene());
}
@Override
public void onActivityStopped(Activity activity) {
if (getTopActivityName() == null) {
onDispatchBackground(getVisibleScene());
}
}
@Override
public void onTrimMemory(int level) {
MatrixLog.i(TAG, "[onTrimMemory] level:%s", level);
if (level == TRIM_MEMORY_UI_HIDDEN && isAppForeground) { // fallback
onDispatchBackground(visibleScene);
}
}
2.2.2 调用plugin的init方法
这里我们具体看tracePlugin的init的方法。
@Override
public void init(Application app, PluginListener listener) {
super.init(app, listener);
MatrixLog.i(TAG, "trace plugin init, trace config: %s", traceConfig.toString());
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
MatrixLog.e(TAG, "[FrameBeat] API is low Build.VERSION_CODES.JELLY_BEAN(16), TracePlugin is not supported");
unSupportPlugin();
return;
}
//猜测跟anr有关
looperAnrTracer = new LooperAnrTracer(traceConfig);
frameTracer = new FrameTracer(traceConfig);
evilMethodTracer = new EvilMethodTracer(traceConfig);
startupTracer = new StartupTracer(traceConfig);
}
具体逻辑后面分析,这里先看主要的流程。后续再单独介绍各个tracer子类。
另外,TracePlugin继承了Plugin基类。父类Plugin的init方法:
@Override
public void init(Application app, PluginListener listener) {
if (application != null || pluginListener != null) {
throw new RuntimeException("plugin duplicate init, application or plugin listener is not null");
}
status = PLUGIN_INITED;
this.application = app;
this.pluginListener = listener;
//监听前后台状态的切换。
AppActiveMatrixDelegate.INSTANCE.addListener(this);
}
简要分析:
感知前后台状态的切换。
2.3 Matrix.init(Matrix matrix)
在看了 plugins 注册和初始化工作之后,是时候要去真正的执行每个plugin的具体逻辑了。
所以,我们需要回到主流程初始化中的Matrix
的init(Matrix matrix)
方法。
private static volatile Matrix sInstance;
public static Matrix init(Matrix matrix) {
if (matrix == null) {
throw new RuntimeException("Matrix init, Matrix should not be null.");
}
synchronized (Matrix.class) {
if (sInstance == null) {
sInstance = matrix;
} else {
MatrixLog.e(TAG, "Matrix instance is already set. this invoking will be ignored");
}
}
return sInstance;
}
没什么东西,通过静态变量sInstance 引用,方便后续使用。
三、类的职责
经过上面的分析,从matrix顶层设计的角度出发,简单的整理出涉及到的类:
四、时序图
以 LooperAnrTrace
为例进行了分析,其他的trace或者plugin也差不多。后续分析到的时候在详细理解
五、总结
matrix类是整个初始化的入口,它负责管理不同功能的plugins,同时还要回调调用者也就是app端插件的生命周期和检测结果。
AppActiveMatrixDelegate类负责监听前后台变化,维护一个前后台的状态。必要时通知监听者。