Muzlash (visnet) — mobil ilovaning foydalanuvchining har qanday harakatlariga uzoq vaqt davomida javob bermaslik holati. Laglar (sekinlashish) va glitchlardan (noto'g'ri xatti-harakat) farqli o'laroq, muzlash UI-ni to'liq bloklaydi: teginishlar qayta ishlanmaydi, animatsiya to'xtaydi, ekran „muzlaydi". Sabab — bosh oqimning sinxron operatsiya bilan bloklanishi, ko'p oqimli koddagi deadlock yoki anomal uzoq axlat yig'ish. Apple Main Thread Checker Documentation ma'lumotlariga ko'ra, iOS-dagi crash hisobotlarining 40% dan ortig'i bosh oqimning bloklanishi bilan bog'liq. Android-da shunga o'xshash vaziyat ANR — „Ilova javob bermaydi" tizim dialogiga olib keladi.
Asosiy fikrlar
Muzlash (freeze, hang) mobil ilovada — ilovaning bir necha soniya yoki undan ko'proq vaqt davomida kirish hodisalarini qayta ishlashni va interfeysni yangilashni to'xtatish holatidir. Texnik jihatdan bu bosh oqim (main thread) bloklanganligini va keyingi runner siklini bajara olmasligini anglatadi.
Lag — 500 ms gacha kechikish bo'lib, foydalanuvchi sekinlashishni sezadi, ammo ilova ishlashda davom etadi. Muzlash 1 soniyadan o'nlab soniyagacha davom etadi. Android-da ANR — 5 soniyadan ortiq davom etgan va tizim tomonidan aniqlangan muzlashning alohida holatidir. Har bir muzlash ANR ga olib kelmaydi, lekin har bir ANR hujjatlashtirilgan muzlashdir.
Android-da 5 soniyadan ortiq muzlash ilovani yopish taklifi bilan ANR dialogini chaqiradi. iOS-da tizim watchdogga ega — agar ilova 10–20 soniya davomida hodisalarga javob bermasa, Watchdog jarayonni 0x8badf00d (ate bad food) kodi bilan tugatadi. Foydalanuvchi ilovaning to'satdan yopilishini va asosiy ekranga qaytishini ko'radi.
100 ms dan ortiq davom etadigan va bosh oqimda ishga tushirilgan har qanday operatsiya potentsial ravishda muzlashga olib keladi. Bloklanishlarning asosiy manbalarini ko'rib chiqamiz.
Katta faylni o'qish, asinxron bo'lmagan tarmoq so'rovi, SharedPreferences da apply va keyin commit sinxron usuli bilan ma'lumotlarni saqlash — bularning barchasi bosh oqimni bloklaydi. Android-da 10 MB faylni sinxron o'qish flesh xotira tezligiga qarab 200–500 ms davom etishi mumkin. iOS-da completionHandler siz URLSession sinxron yuklanishi server javobi vaqtida UI-ni bloklaydi.
Ikki oqim bir-biri tomonidan ushlab turilgan resurslarning bo'shatilishini kutganda deadlock yuzaga keladi. Mobil ilovalarda odatiy stsenariy — A oqimi Lock1 ni bloklaydi va Lock2 ni kutadi, B oqimi esa Lock2 ni bloklaydi va Lock1 ni kutadi. Ikkala oqim ham abadiy muzlaydi. Agar ulardan biri bosh oqim bo'lsa, ilova butunlay muzlaydi.
Mantiqdagi xato — masalan, chiqish shartisiz while(true) yoki bazaviy holatsiz rekursiya — bosh oqimda cheksiz bajarilishga olib keladi. Android buni 5 soniyadan keyin ANR orqali aniqlaydi, iOS esa Stackshot orqali, cheksiz takrorlanuvchi chaqiruv stekini qayd etadi.
Muzlash tashxisi bloklanish vaqtida barcha oqimlarning holatini qayd eta oladigan asboblarni talab qiladi.
Har bir ANR da Android tizimi ilovaning har bir oqimining stek dumpini o'z ichiga olgan /data/anr/traces.txt faylini saqlaydi. Ushbu faylning tahlili — asosiy tashxis usuli: main oqimini topish va u qaysi metodda to'xtaganini ko'rish kerak. Stek Thread.sleep, InputStream.read yoki Lock.lock bilan tugasa, sabab topilgan.
Xcode ilova muzlaganda (SIGSTOP signali) Stackshot — barcha oqimlarning stek tasvirini olishi mumkin. Sxemada „Logging" → „Include Stackshot Logs" ni yoqing. 0x8badf00d kodi bilan qulaganda Devices & Simulators dan crash logini chiqarib, muzlagan stek bilan com.apple.main-thread oqimini toping.
Main Thread Checker ilova ishlayotganda fon oqimlaridan UIKit chaqiruvlarini avtomatik aniqlaydi. Uni sxemada yoqing (Diagnostics → Main Thread Checker). Har bir ogohlantirish potentsial muzlash sababidir, ayniqsa tarmoq so'rovining completionHandler yopilishida yuz bersa.
Android-da StrictMode orqali bloklanishni aniqlash namunasi:
class App : Application() {
override fun onCreate() {
super.onCreate()
StrictMode.setVmPolicy(StrictMode.VmPolicy.Builder()
.detectLeakedSqlLiteObjects()
.detectLeakedClosableObjects()
.penaltyLog()
.build())
StrictMode.setThreadPolicy(StrictMode.ThreadPolicy.Builder()
.detectAll()
.penaltyDeath()
.build())
}
}
Muzlashni bartaraf etish barcha potentsial uzoq operatsiyalarni fon oqimlariga o'tkazish bilan boshlanadi. Har bir platforma uchun aniq texnikalarni ko'rib chiqamiz.
Kotlin Coroutines viewModelScope.launch(Dispatchers.IO) bilan tarmoq operatsiyasi yoki ma'lumotlar bazasidan o'qish fon oqimida bajarilishini kafolatlaydi. Dispatchers.Main faqat UI yangilash uchun ishlatiladi. Muhim: barcha suspend funksiyalar tuzilgan bo'lishi kerak — bolakay korutinlar ota-ona bekor qilinganda bekor qilinadi, oqim oqishining oldini oladi.
Grand Central Dispatch fon vazifalari uchun DispatchQueue.global(qos: .userInitiated) va UI yangilash uchun DispatchQueue.main.async — standart naqsh. Bosh navbatda sync() dan qoching — bu kafolatlangan deadlock. Async/await (Swift 5.5+) dan o'qilishi oson asinxron kod uchun foydalaning, MainActor orqali avtomatik ravishda bosh oqimga qaytish bilan.
Kotlin da synchronized bloklari va Swift da @synchronized bosh oqimida xavflidir: agar boshqa oqim allaqachon bu blokirovkani egallagan bo'lsa, bosh oqim kutishda muzlaydi. Blokirovkalar o'rniga atomik turlardan (AtomicInteger, Swift da atomik xususiyatlar) yoki ketma-ket navbatlardan foydalaning.
Android-da korutinlar bilan asinxron ma'lumot yuklash namunasi:
class DataViewModel : ViewModel() {
private val _data = MutableStateFlow<List<Item>>(emptyList())
val data: StateFlow<List<Item>> = _data.asStateFlow()
fun loadData() {
viewModelScope.launch(Dispatchers.IO) {
val result = fetchFromNetwork()
_data.emit(result)
}
}
}
Muzlashning oldini olish asboblar kombinatsiyasi, arxitektura tamoyillari va kod ko'rib chiqish jarayonlari bilan tizimli ravishda yordam beradi.
Oqim siyosatlari uchun StrictMode ni penaltyDeath bilan sozlang — bu bosh oqimda tarmoq chaqiruvi yoki disk kirish-chiqishi aniqlanganda ilovaning darhol qulashiga olib keladi. Dasturchi muammoni e'tiborsiz qoldira olmaydi. Ishlab chiqarish qurilishida qulashsiz statistika to'plash uchun penaltyLog dan foydalaning.
iOS da Debug sxemasida Main Thread Checker ni yoqing va CI ni ushbu parametr bilan testlarni ishga tushirishga sozlang. Agar test fon oqimidan UIKit chaqiruvini o'z ichiga olsa, muvaffaqiyatsiz bo'lishi kerak. Bu TestFlight ga yuborishdan oldin muammoni aniqlashning yagona ishonchli usulidir.
Kod ko'rib chiqish jarayoniga majburiy band qo'shing: har qanday tarmoq chaqiruvi, fayllar bilan ishlash, ma'lumotlar bazasi yoki og'ir hisoblashlar fon oqimida bajarilishini tekshiring. Deadlock statik analizator bilan aniqlanishi mumkin: Facebook dan Infer va Xcode dan Thread Safety Checker ishga tushirishdan oldin potentsial blokirovkalarni topadi.
Tez-tez beriladigan savollar
ANR (Application Not Responding) — Android ning tizim bildirishnomasi bo'lib, bosh oqim 5 soniyadan ortiq muzlaganda paydo bo'ladi. Muzlash kengroq tushunchadir: har qanday davomiylikdagi UI bloklanishi. iOS da ANR yo'q, lekin 10–20 soniya vaqt chegarasi bilan Watchdog mavjud.
Fayl /data/anr/traces.txt manzilida joylashgan. Kirish uchun root yoki adb shell talab qilinadi: adb shell cat /data/anr/traces.txt \> traces.txt ni root huquqlari bilan bajaring. Stekda „main" oqimini toping — oxirgi chaqirilgan metod bloklanish sababini ko'rsatadi.
Agar muzlash 10 soniyadan kam davom etsa, Watchdog ishga tushmaydi va ilova blokirovka qiluvchi operatsiya tugaguncha shunchaki „muzlab" qoladi. Foydalanuvchi qulashni ko'rmaydi, lekin xafa bo'ladi. Bunday holatlarni aniqlash uchun MetricKit dan bajarilish vaqtining maxsus izlari bilan foydalaning.
Ekran 1 soniyadan kamroq vaqtda ochilishini tekshiradigan UI testlari dan foydalaning. CI ga teginish va keyingi ekran paydo bo'lishi o'rtasidagi vaqtni o'lchashni qo'shing. Android da asinxron operatsiyalarni kutish uchun IdlingResource bilan Espresso dan foydalaning. iOS da yuklash vaqtini tekshirish uchun XCTWaiter bilan XCTest.
SwiftUI o'z-o'zidan muzlashga sabab bo'lmaydi, lekin body xususiyatidagi murakkab hisoblashlar — ha. Body og'ir operatsiyalar tufayli 500 ms hisoblansa, UI muzlaydi. Yechim — hisoblashlarni Task.detached ga o'tkazing va @State ni asosiy aktyorda asinxron yangilang.
Xulosa
Biz kalit topshirig'i bilan mobil ilovani ishlab chiqamiz
IT Sectr 2017-yildan beri startaplar va korxonalar uchun iOS va Android ilovalarini yaratadi. Biz sizga maslahat beramiz va eng yaxshi yechimni taklif qilamiz.
Shuningdek o'qing