You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android MacroBenchmark:FrameTimingMetric仅执行1次迭代失败求助

RecyclerView滚动Macrobenchmark测试仅完成首次迭代即报错的解决办法

问题描述

尝试用FrameTimingMetric对RecyclerView执行5次滚动迭代测试,使用StartupTimingMetric的启动测试能正常完成5次迭代并生成结果,但滚动测试在第一次滚动后就抛出java.lang.IllegalArgumentException: Failed requirement错误,应用退出,剩余4次迭代无法执行。已确认基准模块配置正常,滚动测试中已等待RecyclerView加载完成(数据来自MarkMainActivity的OnCreate方法API请求),日志显示滚动操作已执行。

测试代码

@RunWith(AndroidJUnit4.class)
public class ExampleStartupBenchmark {

    @Rule
    public MacrobenchmarkRule mBenchmarkRule = new MacrobenchmarkRule();

    @Test
    public void startup() {
        mBenchmarkRule.measureRepeated(
                "my-app-package-name",
                Collections.singletonList(new StartupTimingMetric()),
                CompilationMode.DEFAULT,
                StartupMode.COLD,
                5,
                scope -> {
                    scope.startActivityAndWait();
                    return Unit.INSTANCE;
                });
    }

    @Test
    public void scroll() {
        mBenchmarkRule.measureRepeated(
                "my-app-package-name",
                Collections.singletonList(new FrameTimingMetric()),
                CompilationMode.DEFAULT,
                StartupMode.COLD,
                5,
                macrobenchmarkScope -> {
                    
                    Log.i("MacrobenchmarkRuleTAG", "justBeforeIntent");

                    Intent intent = new Intent("MarkMainActivity-intentlaunch-string");

                    macrobenchmarkScope.startActivityAndWait(intent);

                    // Wait until activity is shown.
                    Log.i("MacrobenchmarkRuleTAG", "justBeforeMarkMainActivityWait");
                    macrobenchmarkScope.getDevice().wait(
                            Until.hasObject(By.clazz("MarkMainActivity")),
                            10_000L
                    );

                    Log.i("MacrobenchmarkRuleTAG", "justAfterMarkMainActivityWait");
                    return Unit.INSTANCE;
                }, scope ->{

                    UiDevice device = scope.getDevice();

                    UiObject2 recycler = device.findObject(By.res(scope.getPackageName(), "mark_recyclerview"));
                    SearchCondition<Boolean> searchCond2  = Until.hasObject(By.res("mark_adapter_single_view"));
                    recycler.wait(searchCond2, 10_000L); // wait until recyclerview object loads a singleitemview

                    Log.i("MacrobenchmarkRuleTAG", recycler.getClassName());
           
                    recycler.setGestureMargin(device.getDisplayWidth() / 5);

                    Log.i("MacrobenchmarkRuleTAG", "justbeforefling");
                    recycler.scroll(Direction.DOWN, 55);
             
                    return Unit.INSTANCE;
                });
    }
}

错误栈信息

java.lang.IllegalArgumentException: Failed requirement.
at androidx.benchmark.macro.perfetto.FrameTimingQuery.getFrameSubMetrics(FrameTimingQuery.kt:182)
at androidx.benchmark.macro.FrameTimingMetric.getMetrics$benchmark_macro_release(Metric.kt:231)
at androidx.benchmark.macro.MacrobenchmarkKt.macrobenchmark(Macrobenchmark.kt:209)
at androidx.benchmark.macro.MacrobenchmarkKt.macrobenchmarkWithStartupMode(Macrobenchmark.kt:301)
at androidx.benchmark.macro.junit4.MacrobenchmarkRule.measureRepeated(MacrobenchmarkRule.kt:106)
at com.tc.macrobenchmark.ExampleStartupBenchmark.scroll(ExampleStartupBenchmark.java:51)

解决方案

  • 确保滚动操作产生足够有效帧
    报错核心是FrameTimingQuery未捕获到足够有效帧数据,触发断言失败。当前recycler.scroll(Direction.DOWN, 55)滚动距离可能过短,或滚动后未等帧渲染完成就结束测试。建议改用fling操作(recycler.fling(Direction.DOWN)),或增加滚动距离;滚动后添加device.waitForIdle();,让系统完成帧渲染。

  • 调整启动模式
    目前用StartupMode.COLD每次迭代冷启动,可能导致帧数据采集不稳定。可尝试改为StartupMode.WARM减少初始化开销;若必须冷启动,需确保每次迭代都完整等待RecyclerView数据加载完成,比如判断Item数量是否符合预期。

  • 升级Benchmark库版本
    该错误可能是库的已知问题,建议升级androidx.benchmark:benchmark-macro到最新稳定版本,同时确保测试设备为Android 10及以上。

  • 优化等待逻辑准确性
    现有等待MarkMainActivity的方式不够精准,建议改为等待RecyclerView可见且数据加载完成:

    // 等待RecyclerView可见
    device.wait(Until.hasObject(By.res(scope.getPackageName(), "mark_recyclerview")), 10_000L);
    UiObject2 recycler = device.findObject(By.res(scope.getPackageName(), "mark_recyclerview"));
    // 等待列表至少有5个Item加载完成
    recycler.wait(Until.findObjects(By.res("mark_adapter_single_view")).atLeast(5), 10_000L);
    

    避免空列表滚动导致无帧数据产生。

内容的提问来源于stack exchange,提问作者Bhavesh Aggarwal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 20:13:16