blockcanary是什么?
blockcanary是国内开发者MarkZhai开发的一套性能监控组件,它对主线程操作进行了完全透明的监控,并能输出有效的信息,帮助开发分析、定位到问题所在,迅速优化应用
下图为官方原理介绍示例图:
image.png
简介
特点
非侵入式
使用简单
实时监控
提供完善的堆栈及内存信息
Android渲染机制
Android系统每隔16ms发出VSYNC信号,触发对UI进行渲染, 如果每次渲染都成功,这样就能够达到流畅的画面所需要的60fps,为了能够实现60fps,这意味着程序的大多数操作都必须在16ms内完成。如果超过了16ms那么可能就出现丢帧的情况。
本文主要对blockcanary的原理进行分析,关于渲染的详细机制及优化,推荐参考如下文章:
blockcanary怎么用?
1、gradle引入库
debugImplementation 'com.github.markzhai:blockcanary-android:1.5.0'
releaseImplementation 'com.github.markzhai:blockcanary-no-op:1.5.0'
2、自定义Application并且在onCreate中进行初始化
public class ExampleApplication extends Application {
@Override public void onCreate() {
super.onCreate();
BlockCanary.install(this, new BlockCanaryContext()).start();
}
}
blockcanary核心执行流程是怎样?
blockcanary的核心原理是通过自定义一个Printer,设置到主线程ActivityThread的MainLooper中。MainLooper在dispatch消息前后都会调用Printer进行打印。从而获取前后执行的时间差值,判断是否超过设置的阈值。如果超过,则会将记录的栈信息及cpu信息发通知到前台。
关键类功能说明
类
说明
BlockCanary
外观类,提供初始化及开始、停止监听
BlockCanaryContext
配置上下文,可配置id、当前网络信息、卡顿阈值、log保存路径等
BlockCanaryInternals
blockcanary核心的调度类,内部包含了monitor(设置到MainLooper的printer)、stackSampler(栈信息处理器)、cpuSampler(cpu信息处理器)、mInterceptorChain(注册的拦截器)、以及onBlockEvent的回调及拦截器的分发
LooperMonitor
继承了Printer接口,用于设置到MainLooper中。通过复写println的方法来获取MainLooper的dispatch前后的执行时间差,并控制stackSampler和cpuSampler的信息采集。
StackSampler
用于获取线程的栈信息,将采集的栈信息存储到一个以key为时间戳的LinkHashMap中。通过mCurrentThread.getStackTrace()获取当前线程的StackTraceElement
CpuSampler
用于获取cpu信息,将采集的cpu信息存储到一个以key为时间戳的LinkHashMap中。通过读取/proc/stat文件获取cpu的信息
DisplayService
继承了BlockInterceptor拦截器,onBlock回调会触发发送前台通知
DisplayActivity
用于显示记录的异常信息Activity
代码执行流程
leakcanary的核心流程主要包含3个步骤。
1、init-初始化
2、monitor-监听MainLooper的dispatch时间差,推送前台通知
3、dump-采集线程栈信息及cpu信息
这里先上一下整体的流程图,建议结合源码进行查看。
image
下面我们通过上述3个步骤相关的源码来进行分析。
1、init
根据Application中的使用,我们首先看install方法
public static BlockCanary install(Context context, BlockCanaryContext blockCanaryContext) {
//BlockCanaryContext.init会将保存应用的applicationContext和用户设置的配置参数
BlockCanaryContext.init(context, blockCanaryContext);
//etEnabled将根据用户的通知栏消息配置开启
setEnabled(context, DisplayActivity.class, BlockCanaryContext.get().displayNotification());
return get();
}
接着看get方法的实现如下:
//使用单例创建了一个BlockCanary对象
public static BlockCanary get() {
if (sInstance == null) {
synchronized (BlockCanary.class) {
if (sInstance == null) {
sInstance = new BlockCanary();
}
}
}
return sInstance;
}
接着我们看BlockCanary的对象的构造方法实现如下:
private BlockCanary() {
//初始化lockCanaryInternals调度类
<