blockcanary项目名称AndroidPerformanceMonitor,内含4个模块
1 blockcanary-android-no-op
2 blockcanary-analyzer
3 blockcanary-android
4 blockcanary-sample
本篇文章主要分析blockcanary-analyzer和blockcanary-android
BlockCanary类位于blockcanary-android模块,是整个库的入口
private BlockCanary() {
BlockCanaryInternals.setContext(BlockCanaryContext.get());
mBlockCanaryCore = BlockCanaryInternals.getInstance();
mBlockCanaryCore.addBlockInterceptor(BlockCanaryContext.get());
if (!BlockCanaryContext.get().displayNotification()) {
return;
}
mBlockCanaryCore.addBlockInterceptor(new DisplayService());
}
在构造函数中初始化了BlockCanaryInternals,这是卡顿检测的核心管理类,在BlockCanary中另外两个重要函数就是start和stop,在这里面实际是向主线程Looper中设置自定义printer,根据前后两次调用时间确定是否发生卡顿
public void start() {
if (!mMonitorStarted) {
mMonitorStarted = true;
// 设置自定义printer
Looper.getMainLooper().setMessageLogging(mBlockCanaryCore.monitor);
}
}
public void stop() {
if (mMonitorStarted) {
mMonitorStarted = false;
Looper.getMainLooper().setMessageLogging(null);
mBlockCanaryCore.stackSampler.stop();
mBlockCanaryCore.cpuSampler.stop();
}
}
接下来看BlockCanaryInternals类,位于blockcanary-analyzer中,内部有三个变量,负责不同职能
// 自定义printer
LooperMonitor monitor;
// 堆栈信息采集
StackSampler stackSampler;
// cpu信息采集
CpuSampler cpuSampler;
LooperMonitor是自定义的printer类,在BlockCanary的start函数中被设置进主进程looper,当Looper调用hander处理任务时会产生回调
if (logging != null) {
logging.println(">>>>> Dispatching to " + msg.target + " " +msg.callback + ": " + msg.what);
}
msg.target.dispatchMessage(msg);
if (logging != null) {
logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
}
LooperMonitor会在println回调中区分是调用方法开始还是结束,之后调用堆栈的CPU信息的采集
public void println(String x) {
if (mStopWhenDebugging && Debug.isDebuggerConnected()) {
return;
}
if (!mPrintingStarted) {
mStartTimestamp = System.currentTimeMillis();
mStartThreadTimestamp = SystemClock.currentThreadTimeMillis();
mPrintingStarted = true;
startDump();
} else {
final long endTime = System.currentTimeMillis();
mPrintingStarted = false;
if (isBlock(endTime)) {
notifyBlockEvent(endTime);
}
stopDump();
}
}
startDump和stopDump实际内部都是调用的StackSampler和CpuSampler,这两个类继承自AbstractSampler,在AbstractSampler中由HandlerThreadFactory提供在子线程中进行信息收集工作的HandlerThread,默认情况每个300ms进行一次信息采集
public void start() {
if (mShouldSample.get()) {
return;
}
mShouldSample.set(true);
HandlerThreadFactory.getTimerThreadHandler().removeCallbacks(mRunnable);
HandlerThreadFactory.getTimerThreadHandler().postDelayed(mRunnable,
BlockCanaryInternals.getInstance().getSampleDelay());
}
StackSampler内部包含一个100条容量的LinkedHashMap,存放最近100条堆栈信息
private static final int DEFAULT_MAX_ENTRY_COUNT = 100;
private static final LinkedHashMap<Long, String> sStackMap = new LinkedHashMap<>();
CpuSampler则存着10条容量的LinkedHashMap