欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 汽车 > 维修 > Android性能优化之2个帧率和卡顿监控方案(附实现代码)

Android性能优化之2个帧率和卡顿监控方案(附实现代码)

2025/2/24 16:04:59 来源:https://blog.csdn.net/myth13141314/article/details/143337824  浏览:    关键词:Android性能优化之2个帧率和卡顿监控方案(附实现代码)

本文首发于公众号“AntDream”,欢迎微信搜索“AntDream”或扫描文章底部二维码关注,和我一起每天进步一点点

在 Android 开发中,监控应用的帧率(FPS)是评估应用性能和发现卡顿问题的一个重要指标。本次介绍一些常用的方法来监控 Android 应用的 FPS,包括如何实现这些方法的详细说明和代码示例。

使用 Choreographer API

从 Android 4.1(API 16)开始,Choreographer API 能够帮助开发者在每一帧进行操作,适合用于 FPS 的监控。

判断掉帧和卡顿

在使用 Choreographer API 中,可以通过以下方式判断掉帧或卡顿:

1、 计算帧间隔时间

  • 理想情况下,每帧之间的时间间隔应当是设备的刷新时间,一般为16ms(60 FPS)或8.3ms(120 FPS)等。
  • 监控 doFrame 方法中两次回调的时间差,如果明显高于目标帧时间间隔(例如大于16ms),则说明可能出现掉帧或卡顿。

2、 设置阈值

  • 可以设置一个时间阈值,例如20ms,超过这个时间间隔的即视为掉帧。
  • 连续多次掉帧可以视为卡顿。
实现方案与代码
  1. 创建一个类,使用 Choreographer.FrameCallback 接口来实现帧率监控。
import android.os.Build;
import android.os.Looper;
import android.util.Log;
import android.view.Choreographer;public class FPSMonitor implements Choreographer.FrameCallback {private static final String TAG = "FrameMonitor";private static final long FRAME_INTERVAL_NANOS = 16666666; // 16.6ms in nanoseconds (roughly 60 FPS)private long lastFrameTimeNanos = 0;public void start() {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {Choreographer.getInstance().postFrameCallback(this);} else {// 对于低于 API 16 的设备需要实现兼容方案Log.e(TAG, "Device does not support Choreographer API");}}@Overridepublic void doFrame(long frameTimeNanos) {if (lastFrameTimeNanos == 0) {lastFrameTimeNanos = frameTimeNanos;} else {long elapsedNanos = frameTimeNanos - lastFrameTimeNanos;if (elapsedNanos > FRAME_INTERVAL_NANOS) {long droppedFrames = elapsedNanos / FRAME_INTERVAL_NANOS;Log.w(TAG, "Dropped frames: " + droppedFrames);// 检测到掉帧,打印当前线程的堆栈信息Thread currentThread = Thread.currentThread();StackTraceElement[] stackTraceElements = currentThread.getStackTrace();StringBuilder stackTrace = new StringBuilder("Stack trace:\n");for (StackTraceElement element : stackTraceElements) {stackTrace.append("\tat ").append(element.toString()).append("\n");}Log.i(TAG, stackTrace.toString());}lastFrameTimeNanos = frameTimeNanos;}// Schedule the next frame callbackChoreographer.getInstance().postFrameCallback(this);}
}
  1. 在你的应用中启动 FPS 监控。
public class MainActivity extends AppCompatActivity {private FPSMonitor fpsMonitor;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);fpsMonitor = new FPSMonitor();fpsMonitor.start();}
}

使用 FrameMetrics API 进行掉帧检测

在 Android 7.0(API 24)及更高版本中,你可以使用 FrameMetrics API 来监控应用的帧率和掉帧情况。FrameMetrics 提供了一种强大的方法来衡量和分析视图的绘制性能。

以下是使用 FrameMetrics API 进行掉帧检测的详细介绍和代码示例:

1、 确保设备支持:仅在 API 24 及更高版本上可用,因此需要进行版本检查。

2、 注册 FrameMetrics Listener

我们需要使用 Window 对象来注册一个 OnFrameMetricsAvailableListener,这个监听器会在每一帧结束时提供 FrameMetrics 数据。

示例代码

以下是一个简单的示例,展示如何使用 FrameMetrics API 进行掉帧检测并打印相关信息:

import android.app.Activity;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.FrameMetrics;
import android.view.Window;
import android.view.Window.OnFrameMetricsAvailableListener;public class FrameMetricsActivity extends Activity {private static final String TAG = "FrameMetricsActivity";@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {getWindow().addOnFrameMetricsAvailableListener(new OnFrameMetricsAvailableListener() {@Overridepublic void onFrameMetricsAvailable(Window window, FrameMetrics frameMetrics, int dropCountSinceLastInvocation) {long totalDuration = frameMetrics.getMetric(FrameMetrics.TOTAL_DURATION);long intendedDuration = frameMetrics.getMetric(FrameMetrics.INTENDED_VSYNC_TIMESTAMP) - frameMetrics.getMetric(FrameMetrics.FRAME_PRESENT_TIMESTAMP);// 拿到掉的帧数量Log.d(TAG, "Dropped frames since last: " + dropCountSinceLastInvocation);if (totalDuration > intendedDuration) {Log.w(TAG, "Frame duration exceeded: " + totalDuration);// 当检测到掉帧时打印堆栈信息StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();StringBuilder stackTrace = new StringBuilder("Stack trace:\n");for (StackTraceElement element : stackTraceElements) {stackTrace.append("\tat ").append(element.toString()).append("\n");}Log.i(TAG, stackTrace.toString());}}}, null);} else {Log.e(TAG, "FrameMetrics API not available on this device");}}
}

代码说明

  • TOTAL_DURATION:表示完整帧的时间,包括应用、合成和发布时间。
  • INTENDED_VSYNC_TIMESTAMPFRAME_PRESENT_TIMESTAMP 之间的差值被认为是理想的帧时间。
  • 如果 TOTAL_DURATION 大于理想持续时间,则可能存在掉帧。

注意事项

  • 性能影响:持续监听帧数据可能对性能和电池寿命产生影响,建议仅在开发或调试阶段开启。
  • 日志分析:结合其他性能工具(如 Android Profiler)可以更好地理解应用的性能瓶颈。
  • 应用优化:识别出发生掉帧的代码后,可以通过优化逻辑、减少主线程工作等方式进行优化。
  • 掉帧和卡顿判断需要考虑设备的刷新率,并合理设置阈值。

其他可行方案

SurfaceView 的 FPS 监控

  • 如果使用 SurfaceView,可以在绘制回调中统计帧率。

OpenGL 的 FPS 监控

  • 在使用 OpenGL 渲染时,在每次 SwapBuffers 时统计帧率。

第三方工具

  • TinyDancer、LeakCanary 以及一些性能监控工具也提供了 FPS 监控功能,适合快速应用和调试。

TraceView 和 systrace

  • Android 提供的 TraceViewsystrace 工具可以帮助深度分析性能瓶颈,尽管不是实时监控,但有助于定位问题。

欢迎关注我的公众号AntDream查看更多精彩文章!

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词