How to fix Slow Rendering (Android vitals)(如何修复慢速渲染(Android Vitals))
问题描述
我有一个应用程序在新的 Google Play 控制台 - Android 生命体征部分慢渲染中被列为倒数 25%.我对此感到担忧,因为
这是从 systrace
中获取的两张图片,它展示了 UI 线程在一帧内运行的工作.顶部是使用 layout_width=wrap_content
完成的,底部是使用 layout_width=match_parent
完成的.
我测试过的以下两种方法可以提高帧率:
如果您以较短的跨度(如 16 毫秒)发布可运行文件(
seekBar.postDelayed(runnable, 16)
),您将获得平滑的 60fps:P/s:我还不知道为什么.
使用其他方式更新
count
值,而不是在Runnable
内.使用View.postOnAnimation(Runnable)
重新调度 Runnable.示例项目的结果是 60FPS.
两个使用 postOnAnimation(Runnable)
Runnable
可运行可运行 =新的可运行(){@覆盖公共无效运行(){textView.setText(Integer.toString(count));seekBar.setProgress(count);seekBar.postOnAnimation(this);}};Runnable updateCount = new Runnable() {@Override public void run() {++计数;seekBar.postDelayed(this, 250);}};
I have an app that is listed as in the bottom 25% in the new Google Play Console - Android vitals section for Slow Rendering. I am concerned of this because of such articles that seem to say Google Play may penalize your app in the Play Store rankings if you fall in the bottom 25%.
However, it seems impossible to improve this metric for my app. It plays music and has a SeekBar and TextView which is updated every 250ms as any music player would. I made the minimum basic program to demonstrate:
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);
}
}
Full project here: https://github.com/svenoaks/SlowRendering.git
When I run this program on hardware similar to the Nexus devices, I get these results for a
adb shell dumpsys gfxinfo com.example.xyz.slowrendering
command:
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
This would mean almost all my frames taking >16ms to render, I guess due to the periodic nature of the updating. All other music player apps I have tested also have this Slow Rendering problem as far as I can see. I fear Google's algorithm ruining my app ranking, is there any way I can improve my score?
The TextView
in your layout is causing the problem. Because it has layout width
of wrap_content
, which said that it's width has to be equals to the width of the content (the text in this example). Therefore, every time you call TextView.setText
an expensive measure/layout pass has to occur. Simple setting the layout_width
to match_parent
will solve the issue.
Here are two images what is taken from systrace
, it demonstrate the work run on the UI thread in 1 frame. The top one is done with layout_width=wrap_content
and the bottom one is with layout_width=match_parent
.
Two following methods that i have tested will improve the frame rate:
If you post the runnable in shorter span like 16ms (
seekBar.postDelayed(runnable, 16)
), you get this smooth 60fps:P/s: I am not sure why yet.
Use some other way to update the
count
value instead of inside theRunnable
. UseView.postOnAnimation(Runnable)
to reschedule the Runnable. The result is 60FPS for the sample project.
EDIT:
two Runnable
that uses 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);
}
};
这篇关于如何修复慢速渲染(Android Vitals)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!