Common Ui Freezes in Feedback Apps: Causes and Fixes

Feedback apps live at the intersection of real‑time interaction and heavy background processing. A freeze occurs when the main thread is blocked long enough for the OS to consider the app unresponsive

February 03, 2026 · 5 min read · Common Issues

What Causes UIFreezes in Feedback Apps

Feedback apps live at the intersection of real‑time interaction and heavy background processing. A freeze occurs when the main thread is blocked long enough for the OS to consider the app unresponsive (typically > 5 seconds on Android, > 3 seconds on iOS). In this domain the most common culprits are:

CategoryTypical TriggerWhy It Blocks the UI
Synchronous Network CallsDirect HttpURLConnection/NSURLSession on the UI threadNetwork I/O can take seconds; blocking the thread prevents input events from being processed
Large Bitmap DecodingLoading high‑resolution screenshots or user‑generated images without async handlingDecoding can consume 100‑300 ms per image; repeated on every screen causes cumulative jank
Database Queries on UI ThreadDirect SQLite/Room/CoreData calls without CursorLoader or QueryBuilderDisk I/O stalls the thread, especially when scanning thousands of feedback entries
Complex Layout InflationInflating deep view hierarchies (10+ levels) on every activity launchMeasure/Layout passes become expensive, leading to frame drops
Heavy Animation LoopsContinuously animating progress bars or loading spinners without throttlingEach frame requires layout passes that quickly exceed 16 ms budget
Third‑Party SDK BlockingCrash‑reporting or analytics SDKs performing synchronous initializationSDKs that perform file I/O or network checks during onCreate can lock the UI

These patterns are not unique to feedback apps, but the domain amplifies them because every user interaction is expected to surface a response instantly. A frozen screen means the user never sees their submitted rating, comment, or reaction, eroding trust.

---

Real‑World Impact - User Complaints – In a survey of 2,300 feedback‑app users, 37 % cited “app hangs when I try to submit” as a top pain point.

These numbers are not abstract; they directly affect churn and churn‑rate calculations for product teams that rely on continuous user input.

---

How UI Freezes Manifest in Feedback Apps

Below are concrete, domain‑specific scenarios that developers often miss until users report them:

  1. Submitting a rating while a background sync is in progress – The UI thread waits for the sync to finish before clearing the submit button, causing a temporary lock.
  2. Displaying a paginated list of recent feedback items – Each page loads images synchronously; scrolling freezes mid‑scroll.
  3. Opening the comment modal after tapping a “thumbs‑up” – The modal’s AlertDialog creation includes a heavy layout inflation that stalls input.
  4. Fetching the user’s profile picture to pre‑populate a form field – The image is decoded on the UI thread, freezing the form for 800 ms.
  5. Running a real‑time sentiment analysis on the entered text – The analysis runs on the main thread after each keystroke, causing noticeable lag.
  6. Triggering a server‑side “session expiration” check before allowing a new submission – The check hits a remote endpoint synchronously, blocking the UI.
  7. Showing a loading spinner while awaiting a push‑notification acknowledgment – The spinner is tied to a foreground service that hasn’t been started yet, leading to a deadlock.

Each scenario can be reproduced with a simple script that repeatedly taps the “Submit” button while a network capture tool records latency spikes.

---

Detecting UI Freezes

1. Android: StrictMode & ANR Profiler


    StrictMode.ThreadPolicy.Builder()
        .detectNetwork()          // catches network on UI thread
        .detectAll()              // catches disk & SQLite        .penaltyLog()
        .build()
)

2. iOS: Main Thread Checker & Instruments - Enable Main Thread Checker in Xcode; it throws a runtime exception when a UI‑blocking call is detected.

3. Cross‑Platform (Web)

4. Automated Detection with SUSA

SUSA’s autonomous testing agent can be configured to assert frame budget compliance on key flows (e.g., submit‑feedback). When a frame exceeds the 16 ms threshold, SUSA logs a FREEZE_DETECTED event and automatically generates a regression script to reproduce it.

Detection MethodToolWhat to Look For
Synchronous network on UIStrictMode (Android)NetworkOnMainThreadException
Heavy layout inflationLayout InspectorView hierarchy depth > 8
Blocking DB accessRoom’s Suspending functionsCalls on main thread
Animation jankAndroid Profiler> 16 ms per frame
JS main‑thread blockingChrome DevTools> 50 ms script execution

---

Fixing Each Example – Code‑Level Guidance

1. Async Network Calls


// Bad – synchronous call on UI thread
val response = URL(url).readText()

// Good – coroutine or callback
lifecycleScope.launch {
    val response = withContext(Dispatchers.IO) {
        URL(url).readText()
    }
    updateUI(response)
}

2. Bitmap Decoding


fun decodeBitmap(path: String, targetSize: Int): Bitmap {
    return withContext(Dispatchers.Default) {
        BitmapFactory.decodeFile(path, new BitmapFactory.Options().apply {
            inSampleSize = calculateInSampleSize(targetSize)
        })
    }
}

3. Database Queries


@Dao
interface FeedbackDao {
    @Insert
    suspend fun insert(feedback: Feedback)   // suspend = off‑thread
}

4. Complex Layout Inflation

5. Heavy Animation Loops


// Bad – continuous invalidate()
view.post { progress++ ; invalidate() }

// Good – use ValueAnimator with a limited duration
val animator = ValueAnimator.ofInt(0, 100).apply {
    duration = 1000
    repeatCount = InfiniteLoop
    addUpdateListener { anim ->
        progress = anim.animatedValue as Int
        invalidate()
    }
}
animator.start()

6. Third‑Party SDK Blocking


class MyApp : Application() {
    override fun onCreate() {
        super.onCreate()
        // Light init
        Crashlytics.setUserId(userId)
        // Heavy init moved to a coroutine
        GlobalScope.launch(Dispatchers.IO) {
            HeavyAnalyticsInitializer.init(this)
        }
    }
}

7. Session Expiration Check `kotlin

// Bad – synchronous requestif (isSessionExpired()) throw Exception()

// Good – asynchronous check with timeout

suspend fun checkSession() = withTimeout(3s) {

api.isSessionActive()

}



---

## Prevention: Catching Freezes Before Release  

1. **Integrate Freeze Checks into CI**  
   - Add a Gradle task that runs `adb shell am monitor -w` on a connected device while exercising the submit flow. Fail the build if ANR is logged.  

2. **Static Analysis Rules**  
   - Enable **Detekt** rule `SimplifyUiThread` to flag any `runOnUiThread` blocks longer than 5 ms.  
   - Use **SpotBugs** with `THREAD_SHOULD_NOT_BE_IN_FOREGROUND` to detect blocking I/O.  

3. **Automated Persona‑Based Testing**  
   - Deploy SUSA with the **Impatient** and **Elderly** personas configured to tap “Submit” every 200 ms. SUSA records freeze occurrences and fails the pipeline when a threshold is crossed.  4. **Performance Budgets in Manifest**  
   - Define a **`android:preserveScreenOrientation="false"`** and set `android:windowIsTranslucent="true"` only where necessary to keep the view hierarchy shallow.  

5. **Real‑User Monitoring (RUM) in Production**  
   - Instrument the app with a lightweight tracer that records main‑thread latency every 500 ms. Set alerts when the 95th‑percentile exceeds 200 ms for the “Feedback Submit” screen.  6. **Code Reviews with a Freeze Checklist**  
   - Add items: “Is any network call on the UI thread?”, “Are large bitmaps decoded off‑

Test Your App Autonomously

Upload your APK or URL. SUSA explores like 10 real users — finds bugs, accessibility violations, and security issues. No scripts.

Try SUSA Free