android jankstats

JankStats是一个库,用于追踪和分析Android应用中的性能问题,特别是与帧渲染时间过长(Jank)相关的问题。它基于Android的FrameMetricsAPI和OnPreDrawListener,提供关于应用卡顿的统计信息。开发者可以通过添加依赖、初始化JankStats并在活动的生命周期方法中开启或关闭追踪来使用该库。JankStats提供每帧的详细信息,帮助识别和解决性能瓶颈。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

能力

JankStats 库可帮助您跟踪和分析应用程序中的性能问题。Jank 是指渲染时间过长的应用程序帧,JankStats 库提供有关应用程序卡顿统计信息的报告。

JankStats 建立在现有 Android 平台功能之上,包括 Android 7(API 级别 24)及更高版本上的FrameMetrics API或早期版本上的OnPreDrawListener 。这些机制可以帮助应用程序跟踪完成帧需要多长时间。

用法

添加依赖

implementation "androidx.metrics:metrics-performance:1.0.0-alpha03"

初始化

class JankLoggingActivity : AppCompatActivity() {

    private lateinit var jankStats: JankStats


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // ...
        // metrics state holder can be retrieved regardless of JankStats initialization
        val metricsStateHolder = PerformanceMetricsState.getHolderForHierarchy(binding.root)

        // 初始化JankStats jankFrameListener在用于将信息从平台传递到内部 JankStats 的同一线程上调用
        jankStats = JankStats.createAndTrack(window, jankFrameListener)
        //这个因子乘以当前的刷新率来计算帧持续时间,超过这个时间的帧被认为有jank,默认是2
        jankStats.jankHeuristicMultiplier = 3.0f;
        // 添加状态
        metricsStateHolder.state?.putState("Activity", javaClass.simpleName)
        // ...
    }JankLoggingActivity.kt

开启和关闭控制

override fun onResume() {
    super.onResume()
    jankStats.isTrackingEnabled = true
}

override fun onPause() {
    super.onPause()
    jankStats.isTrackingEnabled = false
}

反馈异常

private val jankFrameListener = JankStats.OnFrameListener { frameData ->
    // A real app could do something more interesting, like writing the info to local storage and later on report it.
    Log.v("JankStatsSample", frameData.toString())
}JankLoggingActivity.kt

产物

FrameData(frameStartNanos=36648326900279, frameDurationUiNanos=209972875, frameDurationCpuNanos=211467511, isJank=true, states=[Navigation: Args(null), Destination(com.example.jankstats:id/messageRecycler) label=Message List class=com.example.jankstats.MessageListFragment])

侦听器提供有关对象卡顿的每帧信息 FrameData。这包含有关所请求帧的以下信息:

  • isjank:一个布尔标志,指示帧中是否发生卡顿。

  • states:您的应用程序在帧中的状态。

原理

初始化 JankStats:传染当前activity的window和监听器

JankStats.createAndTrack(window, jankFrameListener)

init {
        val decorView: View? = window.peekDecorView()
        if (decorView == null) {
            throw IllegalStateException(
                "window.peekDecorView() is null: " +
                    "JankStats can only be created with a Window that has a non-null DecorView"
            )
        }
        //创建holder,用来保存状态
        holder = PerformanceMetricsState.create(decorView)
        //根据版本初始化对应的
        implementation =JankStats,获取帧率的方式不同
            when {
                Build.VERSION.SDK_INT >= 31 -> {
                    JankStatsApi31Impl(this, decorView, window)
                }
                Build.VERSION.SDK_INT >= 26 -> {
                    JankStatsApi26Impl(this, decorView, window)
                }
                Build.VERSION.SDK_INT >= 24 -> {
                    JankStatsApi24Impl(this, decorView, window)
                }
                Build.VERSION.SDK_INT >= 22 -> {
                    JankStatsApi22Impl(this, decorView)
                }
                Build.VERSION.SDK_INT >= 16 -> {
                    JankStatsApi16Impl(this, decorView)
                }
                else -> {
                    JankStatsBaseImpl(this)
                }
            }
        //设置监听回调
        implementation.setupFrameTimer(true)
    }

>= api16 setupFrameTimer

//创建ViewTreeObserver.OnPreDrawListener添加到viewTreeObserver

//在OnPreDrawListener中获取当前帧开始时间,当前时间,帧预期耗时

//调用OnFrameListenerDelegate的onFrame(开始时间,now - 开始时间,预期时间)方法

//在onFrame中判断是不是jank

 override fun setupFrameTimer(enable: Boolean) {
        val decorView = decorViewRef.get()
        decorView?.let {
            if (enable) {
                //通过ViewTreeObserver.OnPreDrawListene来计算当前帧的耗时         
                val delegates = decorView.getOrCreateOnPreDrawListenerDelegator()
                delegates.add(onFrameListenerDelegate)
            } else {
                decorView.removeOnPreDrawListenerDelegate(onFrameListenerDelegate)
            }
        }
    }

端上注册了jankStats.logFrameData监听

private val onFrameListenerDelegate = object : OnFrameListenerDelegate() {
        override fun onFrame(startTime: Long, uiDuration: Long, expectedDuration: Long) {
            jankStats.logFrameData(getFrameData(startTime, uiDuration,
                (expectedDuration * jankStats.jankHeuristicMultiplier).toLong()))
        }
    }
internal open fun getFrameData(
        startTime: Long,
        uiDuration: Long,
        expectedDuration: Long
    ): FrameData {
        metricsStateHolder.state?.getIntervalStates(startTime, startTime + uiDuration,
            stateInfo)
       //判断是不是jank
        val isJank = uiDuration > expectedDuration
        frameData.update(startTime, uiDuration, isJank)
        return frameData
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值