ANR (Application Not Responding) — ez egy Android rendszerüzenet, amely akkor jelenik meg, amikor az alkalmazás több mint 5 másodpercig nem válaszol a felhasználói bevitelre. A Android Developers szerint a fő ok a fő szálon végzett hosszú műveletek, amelyek blokkolják az érintések feldolgozását és a felület megjelenítését. Az ANR mechanizmusainak megértése minden Android-fejlesztő számára szükséges a reszponzív alkalmazások létrehozásához.
Főbb pontok
ANR (Application Not Responding) — ez az Android operációs rendszer párbeszédablaka, amely akkor jelenik meg, amikor az alkalmazás nem válaszol a felhasználói bevitelre. A rendszer az InputDispatcheren keresztül követi nyomon az események feldolgozási idejét: ha egy érintés vagy gombnyomás nem kerül feldolgozásra 5 másodpercen belül, az Android megjelenít egy párbeszédablakot az alkalmazás bezárásának vagy várakozásnak a lehetőségével.
Az ANR mechanizmus védi a felhasználói élményt a lefagyott alkalmazásoktól. Az Android nem engedi, hogy egyetlen alkalmazás blokkolja az egész rendszert — a Desktop operációs rendszerekkel ellentétben a mobil platform kényszerítően korlátozza az események feldolgozási idejét. A BroadcastReceiver 10 másodperces, az foreground szolgáltatás pedig 20 másodperces korláttal rendelkezik.
Az ANR NEM kivétel a kódban — ez egy rendszermechanizmus a Linux folyamatok szintjén. Az Android SIGQUIT jelet küld a folyamatnak, ezután a rendszer az összes szál hívási vermét elmenti a traces.txt fájlba. A fejlesztő az ANR-t nem catch-kivételként, hanem jelentésként kapja az alkalmazás újraindítása után. Az Android 11+ rendszerben megjelent az ApplicationExitInfo API, amely lehetővé teszi a folyamat megszakításának okának programozott lekérését, beleértve az ANR-t — ez leegyszerűsíti a statisztikák gyűjtését a traces.txt manuális elemzése nélkül.
Öt kategória művelet vezet stabilan ANR-hez az Android alkalmazásokban. Mindegyik blokkolja a fő szálat, megakadályozva a rendszert a bemeneti események feldolgozásában és a képernyő újrarajzolásában.
Szinkron HTTP kérések az UI szálon végrehajtva — a leggyakoribb ANR ok a kezdő fejlesztőknél. Még egy gyors kérés a szerverhez is tarthat 1–3 másodpercig, gyenge kapcsolatnál pedig 30 másodpercig vagy többig. Az Android API 11-től kezdve kifejezetten tiltja a hálózati műveleteket a fő szálon, NetworkOnMainThreadException kivételt dobva.
Használjon Coroutines-t vagy RxJava-t aszinkron hívásokhoz. A Dispatchers.IO diszpáccserrel rendelkező korutinok a háttérszálon hajtják végre a kérést, az eredményt pedig a Dispatchers.Main-en keresztül juttatják el a fő szálra. Ez teljesen kiküszöböli az UI szál hálózati műveletek általi blokkolását.
fun fetchUserData() {
CoroutineScope(Dispatchers.Main).launch {
val result = withContext(Dispatchers.IO) {
api.getUserData() // háttérművelet
}
updateUI(result) // eredmény a fő szálon
}
}
Nagy adattömbök feldolgozása, JSON vagy XML elemzése, képek közvetlen kezelése a fő szálon — a második leggyakoribb ANR ok. Már 300 ezredmásodpercnyi megszakítás nélkül működés az UI szálon az eseményhurokba való visszatérés nélkül észrevehető késői megjelenítést okoz, az 5 másodperces határérték pedig ANR-ként kerül rögzítésre.
A WorkManager és a háttérszolgáltatások a nehéz számítások fő szálról történő áthelyezésére szolgálnak. Használja az AsyncTask (elavult), ListenableFuture vagy Kotlin Flow alkalmazást az adatok részletekben történő továbbításához, az UI blokkolása nélkül.
Deadlock akkor fordul elő, amikor két szál zárakat tart és egymásra vár. Ha az egyik szál a fő szál, a rendszer pontosan 5 másodperc után rögzíti az ANR-t. Az UI szálról meghívott Thread.join(), CountDownLatch.await() és synchronized blokkok zárolási kockázatot hordoznak.
Kerüljön minden blokkoló műveletet a fő szálon. A synchronized helyett használjon ConcurrentHashMap-t, a Thread.join() helyett — korutinokat async/await-tel. Ez a szabály minden Android nyelven érvényes: Java, Kotlin vagy C++ JNI-n keresztül.
BroadcastReceiver alapértelmezésben a fő szálon fut. Ha az onReceive() több mint 10 másodpercig elfoglalt, az Android ANR-t jelenít meg. Adatok betöltése az adatbázisból vagy hálózatról az onReceive-on belül garantált út a lefagyáshoz.
Használja a goAsync() függvényt a BroadcastReceiver-en belül a háttérszálra váltáshoz, vagy a registerReceiver-t a getBackgroundBroadcastReceiver()-rel. Ez lehetővé teszi az események feldolgozását az UI blokkolása nélkül.
Nehéz lekérdezések a ContentProvider-hez vagy közvetlen munka az SQLite-tal az UI szálon — kevésbé nyilvánvaló, de gyakori ANR ok. Adatbázis migráció vagy ezrek tömeges beszúrása során a végrehajtási idő meghaladhatja az 5 másodperces korlátot.
Helyezze át az összes adatbázis műveletet a háttérszálakra a Room-on keresztül suspend függvényekkel. A Room automatikusan ellenőrzi, hogy a lekérdezés nem a fő szálon fut-e, és megszegés esetén kivételt dob.
Az ANR diagnosztizálása eltér a szokásos kivételek hibakeresésétől — az ANR-t nem lehet try-catch-ben elkapni. A fő információforrás a traces.txt fájl, amelyet az Android a lefagyás pillanatában hoz létre.
traces.txt tartalmazza az alkalmazás összes szálának hívási vermét az ANR pillanatában. A fájl valós eszközről történő olvasásához hajtsa végre az adb bugreport parancsot, amely teljes rendszerjelentést gyűjt, beleértve az összes közelmúltbeli ANR-t. Az emulátor esetében a fájl a /data/anr/traces.txt címen érhető el. A hívási verem megmutatja, melyik módszer futott a fő szálon a blokkolás pillanatában.
adb bugreport bugreport.zip
unzip -p bugreport.zip "*traces*" > traces.txt
Google Play Console ANR & Crash szekciót biztosít összesített jelentésekkel és hibagyakoriságokkal. Minden ANR-hoz megjelenik a hívási verem és eszközönkénti statisztika: modell, Android verzió, régió. Ez lehetővé teszi azon ANR-k azonosítását, amelyek adott eszközöktől vagy rendszerváltozatoktól függnek.
Az Android Studio 2021 óta tartalmazza az ANR Watchdog-ot a profilozóban. Automatikusan rögzíti a szálak dumpját, ha a fő szál nem válaszol a küszöbértéknél tovább. Az eszköz az események idővonalát mutatja: mely műveletek indultak el, mely módszerek futottak és melyik szakaszban történt a blokkolás.
Az ANR megelőzése egy alapvető szabályon alapul: a fő szál csak UI eseményeket dolgozhat fel. Minden 16 ezredmásodpercnel (egy képkocka ideje) tovább tartó műveletet a háttérszálon kell végrehajtani.
StrictMode — beépített Android eszköz a potenciális ANR-k észlelésére a fejlesztési fázisban. Kapcsolja be az Application.onCreate()-ban lemez- és hálózati műveletek jelzőivel. Megszegés esetén a StrictMode kivételt dob vagy a logcat-be ír.
if (BuildConfig.DEBUG) {
StrictMode.ThreadPolicy.Builder()
.detectDiskReads()
.detectDiskWrites()
.detectNetwork()
.penaltyLog()
.build()
.let { StrictMode.setThreadPolicy(it) }
}
Kotlin Coroutines — az aszinkron munka szabványos módja a modern Android alkalmazásokban. Alapelv: a be- és kimeneti műveletek a Dispatchers.IO-n futnak, az eredmény a Dispatchers.Main-re kerül az UI frissítéséhez. Flow forgatókönyvekhez használja a Dispatchers.Default-ot CPU-igényes feladatokhoz.
RxJava népszerű marad a régebbi projektekben. a subscribeOn(Schedulers.io()) és observeOn(AndroidSchedulers.mainThread()) — minimális készlet az ANR megelőzéséhez. Ugyanaz a szabály: egy Observable vagy Flowable sem bocsáthat ki adatokat a fő szálról.
Firebase Crashlytics az SDK 18.4.0 verziótól dobozból
támogatja az ANR monitorozást. Android 11+ rendszeren a Crashlytics a rendszer ApplicationExitInfo API-ját használja, amely pontos megszakítási okot ad: ANR, Crash vagy rendszer általi megszakítás. Kapcsolja be az egyéni kulcsokat képernyő- és állapotparaméterekkel a kontextuális elemzéshez.
Öt eszköz fedi le az ANR-rel való munka összes szakaszát: a munkaállomáson történő hibakereséstől az éles környezeti monitorozásig. Minden eszköz megoldja a saját feladatát és adatokat szolgáltat különböző forgatókönyvekhez.
| Eszköz | Cél | Adatformátum |
|---|---|---|
| StrictMode | Észlelés fejlesztési fázisban | Logcat / Exception |
| ANR Watchdog (Android Studio) | Valós idejű követés | Thread dump + timeline |
| Google Play Console | Összesített statisztika | ANR rate + stack traces |
| Firebase Crashlytics | Éles monitorozás | ApplicationExitInfo |
| adb bugreport | Teljes rendszerjelentés | traces.txt + logcat + dmesg |
Minden eszköznek megvan a maga rése: a StrictMode a korai szakaszban kapja el a nyilvánvaló megszegéseket, a Crashlytics mutatja az ANR valós gyakoriságát a felhasználóknál, az adb bugreport pedig a legteljesebb képet adja az összetett esetekhez. Kombinálja őket a teljes lefedettség érdekében.
Firebase Performance nyomon követi az UI szál válaszidejét és automatikusan nyomokat hoz létre a gyanísan hosszú műveletekhez. Ha a fő szál több mint 500 ms-ig blokkolódik, a Performance rögzít egy egyéni nyomot a vétkes módszer nevével. Ez lehetővé teszi az ANR forgatókönyvek észlelését felhasználói részvétel nélkül, mielőtt azok kritikussá válnának.
Az Firebase Crashlytics integráció teljes képet ad: a Performance mutatja az ANR előtti lassulásokat, a Crashlytics pedig magát a lefagyás tényét. Állítson be riasztásokat a Firebase Console-ban a 0,1% feletti ANR arány eseményre, és értesítést kap az új problémákról, mielőtt tömeges felhasználói panaszok érkeznének.
Gyakran ismételt kérdések
ANR — olyan lefagyás, amelynél az alkalmazás nem válaszol, de a memóriában marad. Crash — teljes vészhelyzeti befejezés a folyamatból való kilépéssel. Az ANR túlélhető
, ha a rendszer vagy a felhasználó megvárja a választ, a Crash azonban mindig befejezi az alkalmazást.
Nem. Az ANR nem Java/Kotlin kivétel, hanem rendszerjel a folyamatok szintjén (SIGQUIT). A fejlesztő nem tudja feldolgozni az alkalmazás kódjában. Az ANR-re való reagálás egyetlen módja a jelentések elemzése az újraindítás után.
Az eszköz teljesítménye, Android verziója, CPU terhelése és a háttérfolyamatok száma befolyásolja az ANR valószínűségét. Gyengébb eszközökön ugyanaz a művelet 2–3-szor tovább tarthat, így meghaladva az 5 másodperces korlátot.
10 másodperc a szokásos BroadcastReceiver számára az onReceive()-ben. Foreground szolgáltatásoknál a korlát 20 másodperc, a ContentProvider esetében pedig nincs kifejezett korlát, de a fő szál 5 másodperc túlí blokkolása továbbra is ANR-t okoz.
Kapcsolja be a StrictMode-ot az összes debug buildben, adjon hozzá monitorozást Firebase Crashlytics-en keresztül, és használja az adb bugreport-ot, amikor ANR történik. A rendszertelen ANR-k gyakran versenyhelyzetekhez (race condition) vagy speciális hálózati állapotokhoz kapcsolódnak.
Összefoglaló
Kulcsrakész mobilalkalmazást fejlesztünk
Az IT Sectr 2017 óta készít iOS és Android alkalmazásokat induló vállalkozásoknak és vállalkozásoknak. Tanácsot adunk, és a legjobb megoldást javasoljuk.