AhsanAhmed03Introduction Imagine a user opens your Android app, taps a button, and nothing happens. The...
Introduction
Imagine a user opens your Android app, taps a button, and nothing happens.
The screen freezes.
After a few seconds, Android shows:
Application Not Responding (ANR)
Most users don’t wait.
They close the app and uninstall it.
That’s why ANRs are one of the most dangerous performance issues in Android apps.
According to Android Developers documentation, ANRs happen when the main thread is blocked and cannot respond to user input within a specific time.
And if your ANR rate becomes high, Google Play can reduce your app visibility.
So understanding ANRs is not optional — it’s critical.
**What is an ANR? (Simple Explanation)
Official Definition**
ANR occurs when the UI thread is blocked and cannot process user input or draw frames.
Android shows ANR when:
Real-World Example
Think of your app like a restaurant.
Good Flow
Customer orders → Waiter sends to kitchen → Kitchen prepares → Waiter delivers
Everything runs smoothly.
Bad Flow (ANR)
Customer orders → Waiter goes to kitchen and starts cooking himself
Now:
This is exactly what happens when UI thread does heavy work.
Top Causes of ANRs
1. Heavy Work on Main Thread ❌
Problem
Running:
on UI thread.
Android documentation clearly states:
Keep main thread unblocked and move heavy work to worker threads
2. Long Database or Network Operations ❌
Example:
val data = api.getUsers() // running on main thread
This blocks UI.
Result → ANR.
3. BroadcastReceiver Doing Heavy Work ❌
BroadcastReceiver should do small quick tasks only.
If it runs too long → ANR.
Android recommends moving work to background threads.
4. Service Not Starting in Time ❌
Foreground service must call:
startForeground()
within 5 seconds.
Otherwise → ANR.
5. Deadlocks and Thread Blocking ❌
Example:
Thread A waiting for Thread B
Thread B waiting for Thread A
Result:
App freezes.
Android documentation calls this deadlock, a major ANR cause.
**Common Developer Mistakes
❌ Running API calls in Activity**
override fun onCreate() {
super.onCreate()
val users = api.getUsers()
}
Wrong approach.
❌ Large JSON parsing on UI thread
val json = File("data.json").readText()
ANR risk.
Best Practices to Avoid ANRs
✅ Use Coroutines
viewModelScope.launch {
val users = repository.getUsers()
}
Moves work off main thread.
✅ Use Dispatchers.IO
withContext(Dispatchers.IO) {
api.getUsers()
}
Optimized for I/O.
✅ Use Flow for Continuous Data
repository.getUsersFlow()
.flowOn(Dispatchers.IO)
Efficient and non-blocking.
✅ Use WorkManager for Background Tasks
Good for:
✅ Keep BroadcastReceiver Lightweight
override fun onReceive(context: Context, intent: Intent) {
CoroutineScope(Dispatchers.IO).launch {
repository.sync()
}
}
Modern Kotlin Code Example
Repository
class UserRepository(
private val api: UserApi
) {
suspend fun getUsers(): List<User> {
return withContext(Dispatchers.IO) {
api.getUsers()
}
}
}
ViewModel
@HiltViewModel
class UserViewModel @Inject constructor(
private val repository: UserRepository
) : ViewModel() {
private val _users = MutableStateFlow<List<User>>(emptyList())
val users = _users.asStateFlow()
init {
loadUsers()
}
private fun loadUsers() {
viewModelScope.launch {
_users.value = repository.getUsers()
}
}
}
Jetpack Compose UI
@Composable
fun UserScreen(viewModel: UserViewModel) {
val users by viewModel.users.collectAsState()
LazyColumn {
items(users) { user ->
Text(user.name)
}
}
}
Real-World Use Case
Video Fetching App
Scenario:
App scans device videos.
Wrong
Scanning files in Activity.
UI freezes.
ANR occurs.
Correct
Result:
✔ No ANR
✔ Smooth scrolling
✔ Fast loading
✔ Better Play Store rating
**Key Takeaways
Core Rule**
Never block the main thread
Important Points
✔ UI thread must always be free
✔ Move heavy work to background threads
✔ Use Coroutines and Flow
✔ Keep BroadcastReceiver lightweight
✔ Use WorkManager for long tasks
✔ Avoid deadlocks and thread blocking
✔ Monitor ANR in Play Console
Conclusion
ANRs are not just performance issues.
They directly impact:
The safest strategy is simple:
Keep the UI thread clean and move all heavy work to background threads.
If you follow Android’s official guidelines and modern Kotlin practices, ANRs can be almost eliminated.
Feel free to reach out to me with any questions or opportunities at (aahsanaahmed26@gmail.com)
LinkedIn (https://www.linkedin.com/in/ahsan-ahmed-39544b246/)
Facebook (https://www.facebook.com/profile.php?id=100083917520174).
YouTube (https://www.youtube.com/@mobileappdevelopment4343)
Instagram (https://www.instagram.com/ahsanahmed_03/)