BlockCanary源码原理

1.BlockCanary.install(this, AppBlockCanaryContext()).start()
开启监听
<p>public void start() {
if (!mMonitorStarted) {
mMonitorStarted = true;
<strong>Looper.getMainLooper().setMessageLogging(mBlockCanaryCore.monitor);</strong>
}
}</p>
<p>public void setMessageLogging(@Nullable Printer printer) {
<strong>mLogging = printer;</strong>
}</p>
<p>public static void loop() {
......
for (;;) {
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}</p>
<pre><code>        // This must be in a local variable, in case a UI event sets the logger
        **final Printer logging = me.mLogging;
        if (logging != null) {
            logging.println("&gt;&gt;&gt;&gt;&gt; Dispatching to " + msg.target + " " +
                    msg.callback + ": " + msg.what);
        }

        ......
        msg.target.dispatchMessage(msg);
        if (logging != null) {
            logging.println("&lt;&lt;&lt;&lt;&lt; Finished to " + msg.target + " " + msg.callback);
        }
        ......**

} }

基本思路就是通过计算msg的任务的时间,来检测卡顿,看看怎么定位的

LooperMonitor.java @Override 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(); } } 检测时间是1s

private void startDump() { if (null != BlockCanaryInternals.getInstance().stackSampler) { BlockCanaryInternals.getInstance().stackSampler.start(); }

    if (null != BlockCanaryInternals.getInstance().cpuSampler) {
        BlockCanaryInternals.getInstance().cpuSampler.start();
    }
}

public void start() { if (mShouldSample.get()) { return; } mShouldSample.set(true);

    HandlerThreadFactory.getTimerThreadHandler().removeCallbacks(mRunnable);
    HandlerThreadFactory.getTimerThreadHandler().postDelayed(mRunnable,
            BlockCanaryInternals.getInstance().getSampleDelay());
}

延迟时间是800毫秒,

private Runnable mRunnable = new Runnable() { @Override public void run() { doSample();

        if (mShouldSample.get()) {
            HandlerThreadFactory.getTimerThreadHandler()
                    .postDelayed(mRunnable, mSampleInterval);
        }
    }
};

@Override protected void doSample() { StringBuilder stringBuilder = new StringBuilder();

    for (StackTraceElement stackTraceElement : **mCurrentThread.getStackTrace()**) {
        stringBuilder
                .append(stackTraceElement.toString())
                .append(BlockInfo.SEPARATOR);
    }

    synchronized (sStackMap) {
        if (sStackMap.size() == mMaxEntryCount &amp;&amp; mMaxEntryCount &gt; 0) {
            sStackMap.remove(sStackMap.keySet().iterator().next());
        }
        **sStackMap.put(System.currentTimeMillis(), stringBuilder.toString());**
    }
}