In my Android vitals 30% of my users experience slow rendering. My app has a pretty complicated UI so I made a really basic project to try to solve this problem. But it turns out it's pretty slow even with the simplest of layouts.
The layout is a centered text that Android studio offers as a template:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="slowrenderingtest.pichaipls.com.slowrenderingtest.MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/timerView"
android:text="00:00"
android:textSize="40dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
</android.support.constraint.ConstraintLayout>
The activity that uses the layout changes the text every second (because it's a timer):
Timer updateTicks = new Timer();
updateTicks.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
runOnUiThread(new Runnable() {
@Override
public void run() {
Random r = new Random();
timerView.setText(String.format("%02d", r.nextInt(60))+":"+
String.format("%02d", r.nextInt(60)));
}
});
}
}, 100, 1000);
When I turn on GPU profiling, this is getting pretty close to the 16ms limit for drawing each frame on some slower devices (apparently 30% of my users). Just one TextView. But here's the catch: when I first run the activity the rendering times are low but then they shoot up after a few seconds. If I keep touching the screen (there are no controls on the screen), the rendering times remain low. I'm guessing this is due to the CPU/GPU going to a low power state (so rendering takes longer).
My problem is the Android vitals. I keep seeing the warning about slow rendering times (I think anything above 5% of sessions experiencing slow rendering gets a warning) but I don't know how I can speed this up. And I'm worried it may affect my app's ranking but even with this really simple example far too many Android users have slow devices.
Can anything be done about this?
Results show that the fastest layout is Relative Layout, but difference between this and Linear Layout is really small, what we can't say about Constraint Layout. More complex layout but results are the same, flat Constraint Layout is slower than nested Linear Layout.
UI Rendering is the act of generating a frame from your app and displaying it on the screen. To ensure that a user's interaction with your app is smooth, your app should render frames in under 16ms to achieve 60 frames per second (why 60fps?).
Use FrameLayout, RelativeLayout or a custom layout instead. Those layouts will adapt to different screen sizes, whereas AbsoluteLayout will not. Definitely right. I recommend RelativeLayout since it keeps the view hierachy flat.
To optimize layout performance, minimize the number of instantiated layouts and especially minimize deep nested layouts whenever possible. This is why you should generally use a RelativeLayout whenever possible instead of nested LinearLayout .
We're having the same issue is well and after some digging I suspect it's due the CPU getting idle?
Our case is similar. We have a Runnable inside which we update a TextView's text (only) every second using a Handler. The TextView resides on an item inside our RecyclerView. Interestingly, when we scroll the page, or there's some animation going on, or when interacting with the app (basically anything else other than the ticking), we get don't hit the 16ms mark. But let the device be idle and bam, each frame taking between 30-50 ms.
We tried different solutions mentioned in SO for similar situation. Like changing View's width from wrap_content to match_parent. Didn't help with the issue. We tried changing the 1000ms interval to 500, 200, 100, 50, 20, 16, 10 and only saw better results when using 16/10ms (CPU is constantly working?).
Found this article regarding CPU throttling. So probably when the CPU is idle, it's taking some more time to draw the frames?
If you look at CPU monitor in Android Studio, you'll notice CPU becomes idle as soon as nothing is happening. (Higher ones are when there's interaction, and using Nexus 5).
But look the GPU monitor, that looks quite different from the Profile GPU Rendering bars on screen, no frames are actually crossing the 16ms mark! Not sure which GPU monitoring is the correct one. (Big yellow ones are when there's interaction).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With