如何修复Slow Rendering(Android vitals)

时间:2017-05-29 02:27:06

标签: android google-play frame-rate

我有一个应用程序列在新Google Play控制台的最低25% - 用于慢速渲染的Android生命周期部分。我担心这一点,因为such articles似乎说Google Play可能会在Play商店排名中对您的应用进行处罚,如果您跌到最低25%。

但是,似乎无法为我的应用改进此指标。它播放音乐,并有一个SeekBar和TextView,每隔250ms更新一次,就像任何音乐播放器一样。我做了最低限度的基本程序来演示:

public class MainActivity extends AppCompatActivity {

    int count;
    SeekBar seekBar;
    TextView textView;

    Runnable runnable =
            new Runnable() {
                @Override
                public void run() {
                    textView.setText(Integer.toString(count));
                    seekBar.setProgress(count);
                    ++count;
                    seekBar.postDelayed(runnable, 250);
                }
            };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        seekBar = (SeekBar) findViewById(R.id.seek);
        textView = (TextView) findViewById(R.id.text);
        seekBar.post(runnable);
    }
}

此处的完整项目:https://github.com/svenoaks/SlowRendering.git

当我在类似于Nexus设备的硬件上运行此程序时,我得到了这些结果 adb shell dumpsys gfxinfo com.example.xyz.slowrendering命令:

Stats since: 19222191084749ns
Total frames rendered: 308
Janky frames: 290 (94.16%)
90th percentile: 32ms
95th percentile: 36ms
99th percentile: 44ms
Number Missed Vsync: 2
Number High input latency: 0
Number Slow UI thread: 139
Number Slow bitmap uploads: 0
Number Slow issue draw commands: 283

这意味着我的几乎所有帧都需要16毫米才能渲染,我想这是因为更新的周期性。据我所知,我测试的所有其他音乐播放器应用程序也有这个慢渲染问题。我担心Google的算法会破坏我的应用排名,有什么办法可以提高我的分数吗?

2 个答案:

答案 0 :(得分:14)

布局中的TextView导致问题。因为它有layout width wrap_content,它表示它的宽度必须等于内容的宽度(本例中的文本)。因此,每次调用TextView.setText时,都必须进行昂贵的度量/布局传递。将layout_width简单设置为match_parent即可解决问题。

enter image description here

enter image description here

以下是从systrace获取的两张图片,它展示了在1帧中在UI线程上运行的工作。最上面一个是layout_width=wrap_content完成的,最后一个是layout_width=match_parent

我测试的以下两种方法将提高帧速率:

  • 如果你以更短的跨度发布runnable,例如16ms(seekBar.postDelayed(runnable, 16)),你可以得到这个平滑的60fps: enter image description here

    P / s:我不知道为什么。

  • 使用其他方式更新count值而非Runnable内。使用View.postOnAnimation(Runnable)重新安排Runnable。结果是示例项目的60FPS。

编辑: 使用Runnable

的两个postOnAnimation(Runnable)
Runnable runnable =
  new Runnable() {
    @Override
    public void run() {
      textView.setText(Integer.toString(count));
      seekBar.setProgress(count);
      seekBar.postOnAnimation(this);
    }
  };



Runnable updateCount = new Runnable() {
    @Override public void run() {
      ++count;
      seekBar.postDelayed(this, 250);
    }
  };

答案 1 :(得分:2)

我检查了你的代码。不确定这是否是实际代码,或者您是否还有更多内容。在任何情况下,我都会关注android中的一些渲染问题。

<强> 1。 OverDraw

Overdraw是您通过以像素着色而浪费GPU处理时间的地方,这些像素仅通过其他内容再次着色。如果您在父容器布局中添加了背景,然后为子项添加了背景,或者在应用程序主题的样式文件中添加了常用背景,然后在xml的其余部分添加了背景,则这些可能很常见您创建的布局文件。

透支的原因可能是任何事情,请尝试检查您的代码。所有移动设备中都安装了一个开发人员工具,用于检查开发人员选项中的Overdraw。 Here是透支的官方文档。

<强> 2。查看层次结构

为了渲染每个视图,Android经历了三个阶段:

1.测量

2.layout

3.draw

Android完成这些阶段所需的时间与层次结构中的视图数量成正比。我在您的布局文件中看到您有约束布局,其中包括线性布局。我没有看到这个的使用。引入了约束布局以帮助开发人员减少视图层次结构。减少特定布局可以拥有的子项数。还有一个工具可以帮助您解决这个问题。 Here是它的官方android指南。 尝试这些步骤来找出GPU渲染问题。