Android性能:通过Choreographer检测UI丢帧和卡顿

简介:                                          Android性能:通过Choreographer检测UI丢帧和卡顿Android系统每隔16ms重绘UI界面,16ms是因为Android系统规定UI绘图的刷新频率60FPS。

                                         Android性能:通过Choreographer检测UI丢帧和卡顿

Android系统每隔16ms重绘UI界面,16ms是因为Android系统规定UI绘图的刷新频率60FPS。Android系统每隔16ms,发送一个系统级别信号VSYNC唤起重绘操作。1秒内绘制UI界面60次。每16ms为一个UI界面绘制周期。
平常所说的“丢帧”情况,并不是真的把绘图的帧给“丢失”了,也而是UI绘图的操作没有和系统16ms的绘图更新频率步调一致,开发者代码在绘图中绘制操作太多,导致操作的时间超过16ms,在Android系统需要在16ms时需要重绘的时刻由于UI线程被阻塞而绘制失败。如果丢的帧数量是一两帧,用户在视觉上没有明显感觉,但是如果超过3帧,用户就有视觉上的感知。丢帧数如果再持续增多,在视觉上就是所谓的“卡顿”。
丢帧是引起卡顿的重要原因。在Android中可以通过Choreographer检测Android系统的丢帧情况,以作为进一步分析卡顿的基础:

package zhangphil.test;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.Choreographer;
import android.view.View;

public class ANRActivity extends AppCompatActivity {

    private MyFrameCallback mFrameCallback = new MyFrameCallback();

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Choreographer.getInstance().postFrameCallback(mFrameCallback);

        setContentView(R.layout.activity_anr);
        findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                uiLongTimeWork();
            }
        });
    }

    public class MyFrameCallback implements Choreographer.FrameCallback {
        private String TAG = "性能检测";
        private long lastTime = 0;

        @Override
        public void doFrame(long frameTimeNanos) {
            if (lastTime == 0) {
                //代码第一次初始化。不做检测统计。
                lastTime = frameTimeNanos;
            } else {
                long times = (frameTimeNanos - lastTime) / 1000000;
                int frames = (int) (times / 16);

                if (times > 16) {
                    Log.w(TAG, "UI线程超时(超过16ms):" + times + "ms" + " , 丢帧:" + frames);
                }

                lastTime = frameTimeNanos;
            }

            Choreographer.getInstance().postFrameCallback(mFrameCallback);
        }
    }

    private void uiLongTimeWork() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

 

Choreographer周期性的在UI重绘时候触发,在代码中记录上一次和下一次绘制的时间间隔,如果超过16ms,就意味着一次UI线程重绘的“丢帧”。丢帧的数量为间隔时间除以16,如果超过3,就开始有卡顿的感知。

代码运行输出:

07-20 11:23:40.082 5654-5654/zhangphil.test W/性能检测: UI线程超时(超过16ms):17ms , 丢帧:1
07-20 11:23:40.099 5654-5654/zhangphil.test W/性能检测: UI线程超时(超过16ms):17ms , 丢帧:1
07-20 11:23:40.145 5654-5654/zhangphil.test W/性能检测: UI线程超时(超过16ms):28ms , 丢帧:1
07-20 11:23:40.165 5654-5654/zhangphil.test W/性能检测: UI线程超时(超过16ms):20ms , 丢帧:1
07-20 11:23:40.190 5654-5654/zhangphil.test W/性能检测: UI线程超时(超过16ms):24ms , 丢帧:1
07-20 11:23:40.208 5654-5654/zhangphil.test W/性能检测: UI线程超时(超过16ms):17ms , 丢帧:1
07-20 11:23:40.224 5654-5654/zhangphil.test W/性能检测: UI线程超时(超过16ms):17ms , 丢帧:1
07-20 11:23:40.257 5654-5654/zhangphil.test W/性能检测: UI线程超时(超过16ms):33ms , 丢帧:2
07-20 11:23:40.306 5654-5654/zhangphil.test W/性能检测: UI线程超时(超过16ms):24ms , 丢帧:1

 

如果手动点击按钮故意阻塞1秒,丢弃的帧数更多。

相关文章
|
3月前
|
机器学习/深度学习 算法 定位技术
Baumer工业相机堡盟工业相机如何通过YoloV8深度学习模型实现裂缝的检测识别(C#代码UI界面版)
本项目基于YOLOv8模型与C#界面,结合Baumer工业相机,实现裂缝的高效检测识别。支持图像、视频及摄像头输入,具备高精度与实时性,适用于桥梁、路面、隧道等多种工业场景。
317 27
|
18天前
|
存储 消息中间件 人工智能
【04】AI辅助编程完整的安卓二次商业实战-寻找修改替换新UI首页图标-菜单图标-消息列表图标-优雅草伊凡
【04】AI辅助编程完整的安卓二次商业实战-寻找修改替换新UI首页图标-菜单图标-消息列表图标-优雅草伊凡
51 4
|
11月前
|
搜索推荐 Android开发 开发者
探索安卓开发中的自定义视图:打造个性化UI组件
【10月更文挑战第39天】在安卓开发的世界中,自定义视图是实现独特界面设计的关键。本文将引导你理解自定义视图的概念、创建流程,以及如何通过它们增强应用的用户体验。我们将从基础出发,逐步深入,最终让你能够自信地设计和实现专属的UI组件。
|
11月前
|
算法 JavaScript Android开发
|
10月前
|
XML 搜索推荐 前端开发
安卓开发中的自定义视图:打造个性化UI组件
在安卓应用开发中,自定义视图是一种强大的工具,它允许开发者创造独一无二的用户界面元素,从而提升应用的外观和用户体验。本文将通过一个简单的自定义视图示例,引导你了解如何在安卓项目中实现自定义组件,并探讨其背后的技术原理。我们将从基础的View类讲起,逐步深入到绘图、事件处理以及性能优化等方面。无论你是初学者还是有经验的开发者,这篇文章都将为你提供有价值的见解和技巧。
|
11月前
|
XML 前端开发 Android开发
Android:UI:Drawable:View/ImageView与Drawable
通过本文的介绍,我们详细探讨了Android中Drawable、View和ImageView的使用方法及其相互关系。Drawable作为图像和图形的抽象表示,提供了丰富的子类和自定义能力,使得开发者能够灵活地实现各种UI效果。View和ImageView则通过使用Drawable实现了各种图像和图形的显示需求。希望本文能为您在Android开发中使用Drawable提供有价值的参考和指导。
241 2
|
设计模式 Java Android开发
安卓应用开发中的内存泄漏检测与修复
【9月更文挑战第30天】在安卓应用开发过程中,内存泄漏是一个常见而又棘手的问题。它不仅会导致应用运行缓慢,还可能引发应用崩溃,严重影响用户体验。本文将深入探讨如何检测和修复内存泄漏,以提升应用性能和稳定性。我们将通过一个具体的代码示例,展示如何使用Android Studio的Memory Profiler工具来定位内存泄漏,并介绍几种常见的内存泄漏场景及其解决方案。无论你是初学者还是有经验的开发者,这篇文章都将为你提供实用的技巧和方法,帮助你打造更优质的安卓应用。
|
Android开发 开发者 索引
Android实战经验之如何使用DiffUtil提升RecyclerView的刷新性能
本文介绍如何使用 `DiffUtil` 实现 `RecyclerView` 数据集的高效更新,避免不必要的全局刷新,尤其适用于处理大量数据场景。通过定义 `DiffUtil.Callback`、计算差异并应用到适配器,可以显著提升性能。同时,文章还列举了常见错误及原因,帮助开发者避免陷阱。
924 9
|
XML Android开发 UED
💥Android UI设计新风尚!掌握Material Design精髓,让你的界面颜值爆表!🎨
随着移动应用市场的蓬勃发展,用户对界面设计的要求日益提高。为此,掌握由Google推出的Material Design设计语言成为提升应用颜值和用户体验的关键。本文将带你深入了解Material Design的核心原则,如真实感、统一性和创新性,并通过丰富的组件库及示例代码,助你轻松打造美观且一致的应用界面。无论是色彩搭配还是动画效果,Material Design都能为你的Android应用增添无限魅力。
290 1

热门文章

最新文章