Skip to main content

Detecting a screen freeze and ANR issue

This tutorial guides you through identifying main thread (UI thread) delays in your apps using the Kotzilla Platform.

info

Issue context

ANRs (Application Not Responding) occur when the main thread is blocked for too long, making the app unresponsive and causing it to freeze. Common causes include heavy computations or synchronous operations running on the main thread.

Why it matters?

Screen freezes severely degrade user experience and can lead to negative app reviews, higher uninstall rates, and reduced app store rankings.

Suggested user resolution actions

To address these main-thread blockages, aim to reduce time-consuming components on the main thread, particularly main thread resolution times exceeding 100 ms.

  • Monitor for blocking operations: Use the Kotzilla Platform to detect tasks on the main thread that exceed 100 ms.
  • Background thread offloading: Move blocking tasks like I/O operations or data processing off the main thread using background processing techniques.
  • Refactor code: Simplify or optimize complex methods to minimize main thread impact.
  • Offload heavy tasks: Use Koin to ensure that dependencies handling heavy computations or I/O operations are executed on background threads
  • Optimize dependency configuration: Ensure no heavy tasks are performed during dependency creation in Koin modules.

Prerequisites

In this tutorial, we will be using the NowInAndroid app as an example. Before you begin, ensure you've completed the first two steps of the Get started with Kotzilla Platform

Step 1 - Simulate a blockage on the main thread

To observe the effects of blocking on the main thread, we’ll simulate a 1-second delay in MainActivityViewModel. This delay will serve as an example of a blocking operation impacting the app’s main thread performance.

Here’s the code to introduce a 1-second delay in the MainActivityViewModel:

class MainActivityViewModel(
userDataRepository: UserDataRepository,
) : ViewModel() {

init {
// Simulate a main-thread block with a 1-second delay
Thread.sleep(1000)
}
}

Step 2- Create user sessions to capture app execution data.

With the simulated delay added, create a user session that will allow Kotzilla to capture and display the issue.

Follow the navigation steps detailed in this guide to simulate a repeatable sequence of interactions. Repeat this three times to create consistent data on Kotzilla Platform.

Step 3- Analyze results in Kotzilla Platform

3.1 Observing impact on user sessions

After completing these actions, log in to the Kotzilla Platform click on the Dashboard button next to your app to access the app Dashboard View.

Then click on the Sessions View to visualise the list of recorded user sessions. You should see the three sessions created. Notice that the Max Event Duration column for those three sessions reflects the 1-second delay introduced in MainActivityViewModel.

The timeline illustrates the effect of the delay between the started and resumed states of MainActivity, capturing the delay’s impact on app startup performance.

3.2 Investigating the sequence of events

The Kotzilla timeline further reveals the sequence of events during the MainActivityViewModel load, where the delay impacts downstream dependencies and introduces a “spike creation pattern.”

Due to dependency injection occurring on the main thread, tasks initiated by ListenableWorker in the background may also be delayed as they depend on the initialization of components blocked by the main thread.

This delay introduces a potential component structure issue where the dependency graph loads simultaneously increasing the likelihood of performance bottlenecks, particularly during app startup.

Key takeaways

By simulating a 1-second delay in MainActivityViewModel, we explored how Kotzilla Platform detects and analyzes main-thread delays that can lead to ANRs. The tutorial demonstrated how main-thread delays affect the session timeline, dependency structure, and app startup time, providing insights that allow you to optimize dependency loading and avoid blocking operations on the main thread.