In part one of this post, we explored some important optimization strategies to help you improve your appâs stability and performance. This post will take it further and focus on optimizing the performance of your UI to deliver a smooth, premium app experience.
UI hangs
UI hangs occur when your appâs UI becomes unresponsive to user input for an extended time. Itâs normal for there to be a delay between user input and UI response, but once that delay reaches 100ms, it becomes noticeable; if it exceeds 250ms, it will start to frustrate your users.
Letâs take a look at some guidelines and best practices to avoid UI hangs and improve your UIâs performance.
â
Test on low-end devices
In most cases, the majority of your appâs users will be operating mid-range to low-end devices. If you limit your testing to high-end devices, you will miss a variety of performance issues that only occur when the CPU, GPU, and memory are more restrictive.
Free the main thread
Your appâs main thread must remain as unrestricted as possible, and you should offload any non-UI-related work away from the main thread as soon as possibleâthis is a general best practice for mobile app development.
If you need to reflect the result of a process on the UI, always try to notify the main thread through mechanisms like callbacks and observers instead of running it on the main thread.
Switch coroutine context
Kotlin coroutine does a great job of handling threads on Android, allowing you to easily switch between threads to perform different operations. Some popular libraries like Retrofit and Room can internally change a coroutineâs context to a background thread.
If youâre using a similar library, avoid delegating the switching of coroutine contexts to the library itself. This will cause any work done after executing the libraryâs code but before the coroutines end to be handled by your appâs main thread.
â
Manage rendering load
Weâve mentioned avoiding high-resolution images unless necessary before, but we canât talk about UI hangs without bringing in rendering load. High-resolution images place a significant load on the GPU, lowering rendering speed and decreasing UI responsiveness.
Optimize recycler view items
The recycler view is a common source of UI hangs on Android, but the problem doesnât lie in the recycler view component itself. In most cases, the underlying reason is the use of unoptimized items.
While a single item in the recycler view might not present a huge load on the device, recycler views can contain multiple items that need to be rendered, and the number of items can increase as the screen size and resolution increase.
Always keep the number of items in the recycler view and their total size in mind to make sure they can be rendered with reasonable speed.
Dropped frames
Dropped frames are a likely indicator of performance issues. Detecting and investigating them can serve as a good starting point for fixing any major performance issues with your appâs UI rendering.
There are many ways to detect dropped frames in Android. The most basic method is to look into Android Studioâs Logcat while the app is running. You can then filter the logs with the Choreographer tag to find instances where your app failed to render a frame for 333ms or longer, causing it to skip one or more frames.
You can also filter with the OpenGLRenderer tag, which will show you instances where your app failed to render a frame for 700ms.
â
![Android LogCat view showing dropped frames](https://cdn.prod.website-files.com/6270e8022b05abb840d27d6f/63ab94d1c73ddf0ce9087103_dropped-frames-e1669716947668.webp)
Inspect UI rendering
Now that youâve optimized your appâs code and assets and fixed its major UI performance issues, itâs time to take it further and examine your appâs UI rendering to identify janky frames.
Janky frames occur when your app fails to render a frame within the target time of 16.6ms for a device with a 60Hz refresh rate. This causes your appâs animations to stutter, delivering a less-than-optimal experience.
Android provides two different ways to inspect UI rendering performance.
â
On-device GPU rendering
Androidâs on-device developer options include a tool that can help you visualize frame rendering performance. Running your app on a device with GPU rendering profiling enabled will allow you to view a graph representing your appâs rendering performance and identify bottlenecks.
You can read more details about enabling and using on-device GPU rendering in Androidâs documentation.
â
Android Studio profiler
Android Studio provides some tools for analyzing your appâs frame rendering performance and detecting janky frames and hangs. Android Studioâs profiler provides more detailed information and goes well beyond frames and UI, but weâll limit the scope to the UI in this post.
Letâs take a look at an example using Android Studioâs profiler to identify and fix a janky frame.
â
The example in this post uses Android Studio Dolphin and a physical device running Android 12 (API level 31). You can use the Android emulator to run the same Android version or higher.
To begin, run the target app and open Android Studioâs profiler tab. A new session should start automatically, or you can select the â+â button to start a new session manually.
![Screenshot of Android Studio's profiler tab](https://cdn.prod.website-files.com/6270e8022b05abb840d27d6f/63ab94d105d2aaaad29f511a_Android-Studio-profiler-tab-e1669717078548.webp)
Here we can see the timeline graphs for the CPU, memory, and energy usage. Because weâre interested in rendering performance and janky frames, weâll select the CPU graph to view more details.
![Screenshot of Android Studio profiler's CPU profile tab](https://cdn.prod.website-files.com/6270e8022b05abb840d27d6f/63ab94d105d2aa5f689f5119_Android-Studio-CPU-profile-e1669717152346.webp)
The CPU profileâs detailed view gives us more details like user input events, keyboard activity, CPU usage graph, and thread activitiesâwhether they are active, waiting on an I/O operation, or sleeping. The sidebar also provides the option to change the collected data and record our session.
To view UI rendering performance, weâll first enable the system trace option, then select the record button. Now, all we need is to interact with the parts of the app we want to inspect.
![Screenshot of Android Studio profiler's system trace view](https://cdn.prod.website-files.com/6270e8022b05abb840d27d6f/63ab94d1f9470ae15390003a_Android-Studio-system-trace-view-e1669717380552.webp)
When weâre through with the app scenarios that we want to check, weâll stop recording and give Android Studio some time to process the data. Android Studio will open the system trace view once complete.
This view includes a section that identifies janky frames and offers more details about their rendering performance. To discover the reason for a jank, we can select it from the graph and press the âMâ key to zoom in on the selected area and inspect the relevant threads.
The first thread will be the appâs main thread by default; here we can observe all the events that occurred there. With this view, we can identify the long-running operations that caused the jank. In this case, we can see an event highlighted in yellow thatâs taking too long to process. This event represents the rendering of a large 4k image, which we can optimize to avoid this jank.
You can learn more about Android Studioâs profiler and its features from Androidâs documentation.
â
Mobile App Performance Monitoring tools
â
Android Studioâs profiler is a powerful tool that can help you identify and fix issues in your app, but you need more to understand your appâs stability and performance in the real world. Consider mobile App Performance Monitoring (APM) solutions like Instabug that can help you monitor and improve your appâs stability and performance as perceived by your users by giving you detailed reports on crashes, app hangs, app launches, network performance, and much more.
â
![](https://cdn.prod.website-files.com/6270e8022b05abb840d27d6f/63ab94d1268d18359b5eb473_APM-overview-e1669720359928.webp)
Learn more:
- SDK Development Stories: Interviews With Our Developers
- How We Migrated Our Front-End While Scaling at Instabug
- Why We Automated Our Front-End Testing at Instabug
- How We Migrated Our Massive Crashes Database
â
Instabug empowers mobile teams to maintain industry-leading apps with mobile-focused, user-centric stability and performance monitoring.
Visit our sandbox or book a demo to see how Instabug can help your app