Android开发——监控造成UI卡顿的原因

0.  前言

 

Android只有主线程才能更新UI。如果界面1秒钟刷新少于60次,即FPS小于60,用户就会产生卡顿感觉。

Android使用消息机制进行UI更新的,如果在主线程handlerdispatchMessage方法进行了耗时操作,就会发生UI卡顿。

本文原创,转载请注明出处:Android开发——监控造成UI卡顿的原因_SEU_Calvin的博客-CSDN博客

 

1.  dispatchMessage方法在哪

dispatchMessage()是在Looper.loop()里调用,源码如下:

public static void loop() {final Looper me = myLooper();if (me == null) {throw new RuntimeException("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 blockif (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 loggerPrinter logging = me.mLogging;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);}// 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();}
}

所以说,第27行的代码就是可能发生UI卡顿的地方。注意这行代码的前后,有两个logging。也就是说在执行第27代码的前后,如果设置了logging,会分别打印出“>>>>> Dispatching to”和“<<<<< Finished to”这样的Log。这样就给我们监视两次Log之间的时间差,来判断是否发生了卡顿。

2.  设置logging

主要看一下21行的mLogging是什么,源码如下所示:

public final class Looper {private Printer mLogging;public void setMessageLogging(@Nullable Printer printer) {mLogging = printer;}
}
public interface Printer {void println(String x);
}

LoopermLogging是私有的,并且提供了setMessageLogging(@Nullable Printer printer)方法,所以我们可以自己实现一个Printer,在通过setMessageLogging()方法传入即可

public class AppContext extends Application {@Overridepublic void onCreate() {super.onCreate();Looper.getMainLooper().setMessageLogging(new Printer() {private static final String START = ">>>>> Dispatching";private static final String END = "<<<<< Finished";@Overridepublic void println(String x) {if (x.startsWith(START)) {LogMonitor.getInstance().startMonitor();}if (x.startsWith(END)) {LogMonitor.getInstance().removeMonitor();}}});}
}

当我们设置了mLogging之后,loop()方法中就会回调logging.println,并将带有“>>>>> Dispatching to”和“<<<<< Finished to”的字符串传入,我们就可以拿到这两条信息。

如果“>>>>> Dispatching to”信号发生了,我们就假定发生了卡顿(这里我们设定1秒钟的卡顿判定阈值),并且发送一个延迟1秒钟的任务,这个任务就用于在子线程打印出造成卡顿的UI线程里的堆栈信息。而如果没有卡顿,即在1秒钟之内我们检测到了“<<<<< Finished to”信号,就会移除这个延迟1秒的任务。

 

3.  LogMonitor的实现

public class LogMonitor {private static LogMonitor sInstance = new LogMonitor();private HandlerThread mHandlerThread = new HandlerThread("log");private Handler mHandler;private LogMonitor() {mHandlerThread.start();mHandler = new Handler(mHandlerThread.getLooper());}private static Runnable mRunnable = new Runnable() {@Overridepublic void run() {StringBuilder sb = new StringBuilder();StackTraceElement[] stackTrace = Looper.getMainLooper().getThread().getStackTrace();for (StackTraceElement s : stackTrace) {sb.append(s.toString() + "\n");}Log.e("TAG", sb.toString());}};public static LogMonitor getInstance() {return sInstance;}public void startMonitor() {mHandler.postDelayed(mRunnable, 1000);}public void removeMonitor() {mHandler.removeCallbacks(mRunnable);}}

这里我们使用HandlerThread来构造一个HandlerHandlerThread继承自Thread,实际上就一个Thread,只不过它比普通的Thread多了一个Looper,对外提供自己这个Looper对象的get方法,然后创建Handler时将HandlerThread中的looper对象传入。这样我们的mHandler对象就是与HandlerThread这个非UI线程绑定的了,这样它处理耗时操作将不会阻塞UI

总之,如果UI线程阻塞超过1秒,就会在子线程中执行mRunnable,打印出UI线程当前的堆栈信息,如果处理消息没有超过1秒,则会实时的remove掉这个mRunnable

 

4.  测试

Activity中设置一个按钮,并且设置点击后睡3秒。便可以看见打印出的Log信息。帮助我们定位到耗时的地方。





 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/34315.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Android app优化之导致app 卡顿慢的直接原因

大多数用户感知到的卡顿等性能问题的最主要根源都是因为渲染性能。从设计师的角度&#xff0c;他们希望App能够有更多的动画&#xff0c;图片等时尚元素来实现流畅的用户体验。但是Android系统很有可能无法及时完成那些复杂的界面渲染操作。Android系统每隔16ms发出VSYNC信号&a…

android页面卡顿定位,Android界面卡顿分析步骤详解

1、打开ddms工具&#xff0c;位于Sdk\tools\monitor.bat,双击 2、连上手机&#xff0c;选着进程&#xff0c;点击上面的start Method Profiling按钮 image.png 3、点击之后会弹出一个对话框&#xff0c;点击ok即可&#xff0c;然后操作你认为卡顿的界面。再点击一次刚刚的按钮。…

如何监测Android应用卡顿?这篇就够了

本文首发于微信公众号「Android开发之旅」&#xff0c;欢迎关注 Jetpack版Wan-Android项目地址&#xff1a;Android Jetpack架构开发组件化应用实战 欢迎star Flutter版Wan-Android项目地址&#xff1a;Flutter版Wan-Android 欢迎star 卡顿介绍 用户在使用我们应用的时候&am…

Android卡顿优化

一. Android渲染知识 1.1 绘制原理 Android系统要求每一帧都要在 16ms 内绘制完成&#xff0c;平滑的完成一帧意味着任何特殊的帧需要执行所有的渲染代码&#xff08;包括 framework 发送给 GPU 和 CPU 绘制到缓冲区的命令&#xff09;都要在 16ms 内完成&#xff0c;保持流畅…

解决安卓手机卡顿的七个技巧

转载自:http://www.7to.cn/news/detail/3446.html 导读&#xff1a;最近&#xff0c;有用户吐槽自己的手机越来越卡&#xff0c;其实这不是手机的问题&#xff0c;而安卓运行机制的缺陷。虽然安卓系统512MB也能流畅运行&#xff0c;但这仅仅是系统流畅&#xff0c;现在手机APP都…

全网最新:面向Android开发中的“卡顿问题及解决方法”

前言 Android开发中卡顿问题一直是个比较棘手又重要的问题&#xff0c;严重影响用户体验&#xff1b;卡顿是人的一种视觉感受&#xff0c;比如我们滑动界面时&#xff0c;如果滑动不流畅我们就会有卡顿的感觉&#xff0c;这种感觉我们需要有一个量化指标&#xff0c;在编程时如…

Android 卡顿调研

/ 今日科技快讯 / 近日&#xff0c;新华社发文评价盲盒经济称&#xff0c;盲盒不仅成为一个经济现象&#xff0c;也反映了当下中国年轻人&#xff0c;特别是“95后”一代的心理和生活状态。惊喜和期待的背后&#xff0c;“盲盒热”所带来的上瘾和赌博心理也在滋生畸形消费&…

安卓-页面卡顿-分析方法

界面卡顿影响的页面 &#xff1a; ListViewScrollView有动画的页面 分析步骤 打开调试开发者选项&#xff0c;GPU呈现模式分析如果蓝色部分比较高&#xff0c;说明是UI线程性能问题红色部分比较高&#xff0c;应该是DrawList比较复杂&#xff0c;这部分可能跟蓝色部分相关。目…

Android手机为何不再卡顿?性能优化才是安卓起飞关键

现在谈到挂载 Android系统的 手机&#xff0c;大部分人的印象早已不像前几年&#xff0c;几年前的安卓机那是用了一段时间就变得有点卡顿&#xff0c;用1年就卡的动弹不得&#xff0c;不得不每年都更换新机。 为什么以前会出现这种情况呢&#xff1f;其实主要是有些程序在运行…

Android App 反应卡顿解决方案

Android App 反应卡顿&#xff0c;从技术上将就是UI 渲染慢。 UI渲染是从您的应用程序生成一个框架并将其显示在屏幕上的行为。 为了确保用户与您的应用程序的交互顺利&#xff0c;您的应用程序应该在16ms内渲染帧数达到每秒60帧&#xff08;为什么60fps&#xff1f;&#xff…

中文大模型评估基准:C-EVAL: A Multi-Level Multi-Discipline Chinese Evaluation Suite for Foundation Models

论文&#xff1a;https://arxiv.org/abs/2305.08322 网站&#xff1a;C-Eval: A Multi-Level Multi-Discipline Chinese Evaluation Suite for Foundation Models 一、导言 随着大语言模型的迅速发展&#xff0c;如何评估一个大模型的能力也成为了一个重要的话题&#xff0c…

「国际科技信息中心SCITIC论坛」从细胞、基因和人工智能,探讨智慧医疗的机遇和挑战...

点击蓝字 关注我们 AI TIME欢迎每一位AI爱好者的加入&#xff01; 2023年3月22日&#xff0c;由国际科技信息中心主办&#xff0c;AI TIME承办的SCITIC论坛“细胞&#xff0c;基因和人工智能&#xff1a;探索医学研究的未来”完美收官。SCITIC论坛由国际科技信息中心倾力打造&a…

C-Eval:构造中文大模型的知识评估基准

作者&#xff1a;符尧&#xff0c;何俊贤 排版&#xff1a;宋梓瑜 来源&#xff1a;海外独角兽 本项目立项于 2023 年 2 月 28 日&#xff0c;由上海交通大学、清华大学和爱丁堡大学共同完成&#xff0c;发布于 2023 年 5 月 22 日&#xff0c;原文链接&#xff1a;https://yao…

GPT(Chat)原理及其应用

摘要 遥想以往&#xff0c;人类沟通的方式只有口头或书面文字&#xff0c;但现在随着科技的发展&#xff0c;人类的沟通方式又得到了革命性的变化&#xff0c;即通过聊天机器人实现人机沟通。而GPT(Chat)中文聊天机器人又是其中的一种&#xff0c;它可以通过技术手段来自然地与…

AI:什么是智能?

本篇文章是博主在人工智能等领域学习时&#xff0c;用于个人学习、研究或者欣赏使用&#xff0c;并基于博主对人工智能等领域的一些理解而记录的学习摘录和笔记&#xff0c;若有不当和侵权之处&#xff0c;指出后将会立即改正&#xff0c;还望谅解。文章分类在学习摘录和笔记专…

ChatGPT推荐的开源项目,到底靠不靠谱?

今天我们让ChatGPT推荐一些开源项目&#xff0c;看看这些项目到底靠不靠谱&#xff1f; 首先&#xff0c;我们需要明确一个概念&#xff0c;那就是什么是开源项目。开源项目是指代码开放、可自由使用、修改和分发的软件项目。开源项目的优点显而易见&#xff0c;它们免费、透明…

餐饮行业最新的经营模式——私域运营案例

疫情让许多企业发展面临巨大压力&#xff0c;而私域流量在这个时刻成为很多餐饮企业爱如珍宝的“救命稻草”。甚至有人预言&#xff0c;今年将可能是餐饮私域流量醒觉得第一年。目睹着越来越多的餐饮企业其中甚至还有餐饮大牌企业都加入私域流量中来。但好多餐饮人都不太了解私…

基于PHP的餐饮行业管理系统

第一章 绪论 1.1 系统开发背景 近年来&#xff0c;基于用户对网络信息传递的实时性以及高效性等方面的需求&#xff0c;使得信息化技术手段以及相关的产业结构得到的飞速的发展&#xff0c;其中最为出众的当属电商化的运营管理模式&#xff0c;其一经推广便受到了广泛的关注。…

【完善】微信餐厅点单小程序+后台管理系统的设计与实现(python实现)

前言 本文为完善上一篇文章餐厅点单小程序后台管理管理系统的设计与实现&#xff0c;旨在帮助有需要的小伙伴&#xff0c;更好的入门学习python3 djangovue开发的前后端分离框架。话不多说&#xff0c;开始我们的学习吧&#xff5e; 项目介绍 本次系统设计分两大模块&#x…

餐饮门店数字化转型|餐厅管理系统小程序

餐饮行业规模非常庞大&#xff0c;每年都有大量公司或个体户入局&#xff0c;国内各类美食非常多&#xff0c;不同品类菜品都有大量需求&#xff0c;以前几乎在业的餐饮门店&#xff0c;只要运营得当&#xff0c;挣多挣少总归是有利的&#xff0c;也能很好的生存下去&#xff0…