流程优化

2019年第一篇技术文,新年快乐~

目录

如何解决卡顿问题?

Android UI卡顿怎么进行监测?

ANR原理(回答主线程阻塞5秒不算,要分析源码)。


 

如何解决卡顿问题?

常见问题:
  - 过度绘制,层级过深。
  - 主线程耗时大的函数、滑动过程中的CPU工作问题。
   
    主线程里占用CUP时间很长的函数,特别关注IO操作(文件IO、网络IO、数据库操作等),
    主线程调用次数多的函数

工具:
  - Profile GPU Rendering(Profile GPU Rendering)
  - 设备过渡绘制查看功能、HierarchyViewer等
  - Lint静态代码分析工具
  - Traceview

Android UI卡顿怎么进行监测?

1. 利用UI线程Looper打印的日志。
  - UI线程中的Looper,在其loop方法中会不断取出Message,调用其绑定的Handler在UI线程进行执行。

public static void loop() {
    final Looper me = myLooper();

    final MessageQueue queue = me.mQueue;

    for (;;) {
        Message msg = queue.next(); // might block
        // This must be in a local variable, in case a UI event sets the logger
        Printer logging = me.mLogging;
        if (logging != null) {
            logging.println(">>>>> Dispatching to " + msg.target + " " +
                    msg.callback + ": " + msg.what);
        }
        // focus
        msg.target.dispatchMessage(msg);

        if (logging != null) {
            logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
        }

   
        }
        msg.recycleUnchecked();
    }
}

如果设置了logging,会分别打印出>>>>> Dispatching to和<<<<< Finished to这样的log。

public class BlockDetectByPrinter {

    public static void start() {

        Looper.getMainLooper().setMessageLogging(new Printer() {

            private long startTime;   
        private long blockThreshold;
        private long startedPrinting;

            @Override
            public void println(String x) {
                if (!startedPrinting) {
                mStartTimeMillis = System.currentTimeMillis();
                   startedPrinting = SystemClock.currentThreadTimeMillis();
                   mStartedPrinting = true;
            } else {
                final long endTime = System.currentTimeMillis();
                startedPrinting = false;
            //判断是否为卡顿
                   if (isBlock(endTime)) {
                StringBuilder sb = new StringBuilder();
                    StackTraceElement[] stackTrace = Looper.getMainLooper().getThread().getStackTrace();
                        for (StackTraceElement s : stackTrace) {
                              sb.append(s.toString() + "\n");
                       }
                   }
            }
            }
        });
    }
    
    private boolean isBlock(long endTime) {
        return endTime - startTime > blockThreshold;
    }
    
}
```
可以通过 `Looper.getMainLooper().setMessageLogging(mainLooperPrinter);`
并在mainLooperPrinter中判断start和end,来获取主线程dispatch该message的开始和结束时间,并判定该时间超过阈值(如2000毫秒)为主线程卡慢发生,并dump出各种信息。

ANR原理(回答主线程阻塞5秒不算,要分析源码)。

ANR(Application Not responding),是指应用程序未响应,Android系统对于一些事件需要在一定的时间范围内完成,如果超过预定时间能未能得到有效响应或者响应时间过长,都会造成ANR。    

 造成ANR的场景:
- Service Timeout:服务在20s内未执行完成;
- BroadcastQueue Timeout:比如前台广播在10s内执行完成
- ContentProvider Timeout:内容提供者执行超时
- InputDispatching Timeout: 输入事件分发超时5s,包括按键分发事件的超时。


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部