BlockCanary 核心原理分析


    参考:

    public static void loop() {
        final Looper me = myLooper();
        if (me == null) {
            throw new RuntimeEx ception("No Looper; Looper.prepare() wasn't called on 
            this thread. ");
        }
        final MessageQueue queue = me.mQueue;
        // Make sure the identity of this thread is that of the local process,
        // and keep track of what that identity token actually is.
        Binder.clearCallingIdentity();
        final long ident = Binder.clearCallingIdentity();
        for (; ; ) {
            Message msg = queue.next(); // might block
            if (msg == null) {
                // No message indicates that the message queue is quitting.
                return;
            }
            // 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(">>>>> Dispatching to " + msg.target + " " +
                        msg.callback + ": " + msg.what);
            }
            final long traceTag = me.mTraceTag;
            if (traceTag != 0 && Trace.isTagEnabled(traceTag)) {
                Trace.traceBegin(traceTag, msg.target.getTraceName(msg));
            }
            try {
                msg.target.dispatchMessage(msg);
            } finally {
                if (traceTag != 0) {
                    Trace.traceEnd(traceTag);
                }
            }
            if (logging != null) {
                logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
            }
            // Make sure that during the course of dispatching the
            // identity of the thread wasn't corrupted.
            final long newIdent = Binder.clearCallingIdentity();
            if (ident != newIdent) {
                Log.wtf(TAG, "Thread identity changed from 0x"
                        + Long.toHexString(ident) + " to 0x"
                        + Long.toHexString(newIdent) + " while dispatching to "
                        + msg.target.getClass().getName() + " "
                        + msg.callback + " what=" + msg.what);
            }
            msg.recycleUnchecked();
        }
    }
原理:我们只需要计算打印这两天 log 的时间差,就能得到 dispatchMessage 的耗时,android
提供了 Looper.getMainLooper().setMessageLogging(Printer printer)来设置这个 logging 对
象,所以只要自定义一个 Printer,然后重写 println(String x)方法即可实现耗时统计了。
通过在 DispatchMessage 的方法的执行时间,来判断卡顿,管是哪种回调方式,回调一定发
生在 UI 线程。因此如果应用发生卡顿,一定是在 dispatchMessage 中执行了耗时操作。我
们通过给主线程的 Looper 设置一个 Printer,打点统计 dispatchMessage 方法执行的时间,
如果超出阀值,表示发生卡顿,则 dump 出各种信息,提供开发者分析性能瓶颈。
mBlockListener.onBlockEvent
 
https://blog.csdn.net/lhd201006/article/details/79044497
 

Android UI卡顿监测框架BlockCanary原理分析

https://www.jianshu.com/p/e58992439793

猜你喜欢

转载自blog.csdn.net/houdada_/article/details/106973216