Pag-freeze sa development — esensya, dahilan at pag-iwas

May-akda: IT Sectr Nai-publish: 2026-07-28 Oras ng pagbabasa: 9 min

Pag-freeze (visnet) — ay isang estado kung saan ang mobile app ay tumitigil sa pagtugon sa anumang aksyon ng user sa mahabang panahon. Hindi tulad ng lag (pagbagal) at glitches (maling pag-uugali), ang pag-freeze ay ganap na hinaharangan ang UI: hindi pinoproseso ang mga pagpindot, humihinto ang animation, ang screen ay „nag-freeze". Ang dahilan — pag-block ng main thread ng isang synchronous na operasyon, deadlock sa multi-thread code, o abnormal na mahabang garbage collection. Ayon sa Apple Main Thread Checker Documentation, mahigit 40% ng mga crash report sa iOS ay nauugnay sa pag-block ng main thread. Sa Android, ang katulad na sitwasyon ay humahantong sa ANR — system dialog na „Hindi tumutugon ang app".

Mga pangunahing punto

  • Pag-freeze — kumpletong pag-block ng UI sa mahabang panahon (mga segundo at sampung segundo), naiiba sa lag at glitches
  • Mga pangunahing dahilan — pag-block ng main thread ng input-output, deadlock sa pagitan ng mga thread, walang katapusang loop at memory leak na may mahabang GC
  • Diagnosis ay kinabibilangan ng Main Thread Checker sa iOS, ANR logs /data/anr/traces.txt sa Android at pagsusuri ng thread dumps
  • Pagtanggal — paglipat ng lahat ng potensyal na mahabang operasyon sa background threads, paggamit ng Structured Concurrency at pag-iwas sa synchronized sa UI thread
  • Pag-iwas — StrictMode, Main Thread Checker sa Debug schema, static analysis para sa deadlock at pana-panahong pagtakbo ng mga test na may pagsukat ng oras ng tugon

Ano ang pag-freeze sa mobile development

Pag-freeze (freeze, hang) sa isang mobile app — ay isang estado kung saan ang app ay tumitigil sa pagproseso ng input events at pag-update ng interface sa loob ng ilang segundo o higit pa. Sa teknikal, ito ay nangangahulugan na ang main thread ay naka-block at hindi maisakatuparan ang susunod na runner cycle.

Pagkakaiba sa pagitan ng pag-freeze, lag, at ANR

Lag — ay isang pagkaantala hanggang 500 ms, kung saan napapansin ng user ang pagbagal, ngunit patuloy na gumagana ang app. Pag-freeze ay tumatagal mula 1 segundo hanggang sampung segundo. ANR sa Android — ay isang espesyal na kaso ng pag-freeze na tumagal nang higit sa 5 segundo at natukoy ng system. Hindi lahat ng pag-freeze ay humahantong sa ANR, ngunit ang bawat ANR ay isang dokumentadong pag-freeze ng system.

Mga kahihinatnan ng pag-freeze

Sa Android, ang pag-freeze ng higit sa 5 segundo ay nagdudulot ng ANR dialog na may mungkahing isara ang app. Sa iOS, ang system ay may watchdog — kung ang app ay hindi tumugon sa mga event sa loob ng 10–20 segundo, tinatapos ng Watchdog ang proseso gamit ang code 0x8badf00d (ate bad food). Nakikita lamang ng user ang biglaang pagsasara ng app at pagbabalik sa home screen.

Mga dahilan ng pag-freeze sa Android at iOS

Ang bawat operasyon na tumatagal ng higit sa 100 ms at pinapatakbo sa main thread ay potensyal na nagdudulot ng pag-freeze. Tingnan natin ang mga pangunahing pinagmumulan ng pag-block.

Synchronous input-output sa UI thread

Pagbasa ng malaking file, network request na walang asynchrony, pag-save ng data sa SharedPreferences sa pamamagitan ng synchronous method na apply na sinusundan ng commit — lahat ng operasyong ito ay humaharang sa main thread. Sa Android, ang synchronous na pagbasa ng 10 MB file ay maaaring tumagal ng 200–500 ms depende sa bilis ng flash memory. Sa iOS, ang synchronous na URLSession load na walang completionHandler ay humaharang sa UI habang naghihintay ng tugon ng server.

Deadlock sa multi-thread code

Kapag ang dalawang thread ay naghihintay na pakawalan ang mga resources na hawak ng isa't isa, nangyayari ang deadlock. Sa mga mobile app, tipikal na senaryo — thread A ay humaharang sa Lock1 at naghihintay ng Lock2, habang thread B ay humaharang sa Lock2 at naghihintay ng Lock1. Parehong thread ay nag-freeze magpakailanman. Kung ang isa sa kanila ay ang main thread, ang app ay ganap na nag-freeze.

Walang katapusang loop o recursion

Error sa logic — halimbawa while(true) na walang exit condition o recursion na walang base case — humahantong sa walang katapusang pag-execute sa main thread. Android ay natutukoy ito sa pamamagitan ng ANR pagkalipas ng 5 segundo, iOS — sa pamamagitan ng Stackshot, na nagre-record ng walang katapusang umuulit na call stack.

  • Android — Cursor na hindi sarado, synchronous request sa pamamagitan ng execute() sa halip na enqueue(), FileInputStream.read() sa UI thread
  • iOS — performSelectorOnMainThread:withObject:waitUntilDone:YES, pagpapatakbo ng NSURLConnection sendSynchronousRequest, pag-load ng imahe gamit ang dataWithContentsOfURL
  • Cross-platform — Flutter compute na walang dedicated isolate, React Native synchronous NativeModule

Paano i-diagnose ang pag-freeze

Ang diagnosis ng pag-freeze ay nangangailangan ng mga tool na may kakayahang mag-record ng estado ng lahat ng thread sa sandali ng pag-block.

ANR logs sa Android

Sa bawat ANR, ang Android system ay nagse-save ng file na /data/anr/traces.txt, na naglalaman ng stack dump ng bawat thread ng app. Ang pagsusuri ng file na ito — pangunahing paraan ng diagnosis: hanapin ang main thread at tingnan kung saang metodo ito huminto. Kung ang stack ay nagtatapos sa Thread.sleep, InputStream.read o Lock.lock — natagpuan na ang dahilan.

Stackshot sa iOS

Xcode kapag nag-freeze ang app (signal SIGSTOP) ay maaaring kumuha ng Stackshot — snapshot ng stacks ng lahat ng thread. I-on sa schema ang „Logging" → „Include Stackshot Logs". Sa crash na may code 0x8badf00d, kunin ang crash log mula sa Devices & Simulators at hanapin ang thread com.apple.main-thread na may frozen na stack.

Main Thread Checker sa Xcode

Main Thread Checker ay awtomatikong nakakatuklas ng mga tawag sa UIKit mula sa background threads habang tumatakbo ang app. I-on ito sa schema (Diagnostics → Main Thread Checker). Ang bawat babala ay potensyal na dahilan ng pag-freeze, lalo na kung ito ay nangyayari sa pagsasara ng completionHandler ng network request.

Halimbawa ng pagtuklas ng pag-block sa pamamagitan ng StrictMode sa Android:

kotlin
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())
    }
}

Mga paraan ng pagtanggal ng UI blockages

Ang pag-aayos ng pag-freeze ay nagsisimula sa paglipat ng lahat ng potensyal na mahabang operasyon sa background threads. Tingnan natin ang mga tiyak na pamamaraan para sa bawat platform.

Structured Concurrency gamit ang coroutines

Kotlin Coroutines na may viewModelScope.launch(Dispatchers.IO) ay ginagarantiyahan na ang network operation o pagbasa ng database ay isinasagawa sa background thread. Ang Dispatchers.Main ay ginagamit lamang para sa pag-update ng UI. Mahalaga: lahat ng suspend functions ay dapat naka-structure — ang mga child coroutine ay kinakansela kapag kinakansela ang parent, pumipigil sa thread leak.

Asynchronous queues sa iOS

Grand Central Dispatch na may DispatchQueue.global(qos: .userInitiated) para sa background tasks at DispatchQueue.main.async para sa UI updates — karaniwang pattern. Iwasan ang sync() sa main queue — ito ay garantisadong deadlock. Gamitin ang async/await (Swift 5.5+) para sa mas madaling basahin na asynchronous code na may awtomatikong pagbabalik sa main thread sa pamamagitan ng MainActor.

Pag-iwas sa synchronized sa UI thread

Ang synchronized blocks sa Kotlin at @synchronized sa Swift sa main thread ay mapanganib: kung ang ibang thread ay nakuha na ang lock na ito, ang main thread ay mag-freeze sa paghihintay. Gamitin ang atomic types (AtomicInteger, atomic properties sa Swift) o sequential queues sa halip na locks.

Halimbawa ng asynchronous na pag-load ng data gamit ang coroutines sa Android:

kotlin
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)
        }
    }
}

Pag-iwas sa pag-freeze sa yugto ng development

Ang pagpigil sa pag-freeze nang sistematiko ay tinutulungan ng kombinasyon ng mga tool, prinsipyo ng arkitektura, at proseso ng code review.

StrictMode na may penaltyDeath

I-configure ang StrictMode na may penaltyDeath para sa thread policies — ito ay magdudulot ng agarang crash ng app kapag may nakitang network call o disk I/O sa main thread. Hindi maaaring balewalain ng developer ang problema. Sa production build, gamitin ang penaltyLog para sa pagkolekta ng statistics nang walang crashes.

Main Thread Checker sa Debug schema

Sa iOS, i-on ang Main Thread Checker sa Debug schema at i-configure ang CI na magpatakbo ng mga test gamit ang opsyong ito. Kung ang test ay naglalaman ng UIKit call mula sa background thread — dapat itong mabigo. Ito ang tanging maaasahang paraan upang matukoy ang problema bago ipadala sa TestFlight.

Code review na may check ng multi-threading

Magdagdag sa proseso ng code review ng mandatoryong punto: suriin na ang bawat network call, trabaho sa files, database, o mabibigat na computations ay isinasagawa sa background thread. Ang Deadlock ay maaaring matukoy ng static analyzer: Infer mula sa Facebook at Thread Safety Checker mula sa Xcode ay nakakahanap ng potensyal na pag-block bago pa man patakbuhin.

  • Android — StrictMode, Infer, Android Lint Multithread, Kotlin Coroutines na may viewModelScope
  • iOS — Main Thread Checker, TSAN (Thread Sanitizer), Xcode Analyze, Swift async/await na may MainActor
  • Cross-platform — Flutter compute isolate, React Native interaction manager na may requestAnimationFrame

Mga madalas itanong

Ano ang pagkakaiba ng pag-freeze at ANR?

ANR (Application Not Responding) — ay isang system notification ng Android na lumalabas kapag nag-freeze ang main thread nang higit sa 5 segundo. Ang pag-freeze ay mas malawak na konsepto: anumang pag-block ng UI ng anumang tagal. Sa iOS ay walang ANR, ngunit mayroong Watchdog na may timeout na 10–20 segundo.

Paano basahin ang traces.txt sa Android?

Ang file ay matatagpuan sa /data/anr/traces.txt. Para sa access, kinakailangan ang root o adb shell: isagawa ang adb shell cat /data/anr/traces.txt \> traces.txt na may root privileges. Sa stack, hanapin ang thread na „main" — ang huling tinawag na metodo ay nagpapahiwatig ng dahilan ng pag-block.

Bakit nag-freeze ang app sa iOS ngunit hindi nag-crash?

Kung ang pag-freeze ay tumatagal nang mas mababa sa 10 segundo, hindi nag-activate ang Watchdog, at ang app ay „nag-freeze" lamang hanggang matapos ang blocking operation. Hindi nakakakita ang user ng crash, ngunit nakakaranas ng pagkabigo. Para matukoy ang ganitong mga kaso, gamitin ang MetricKit na may custom na execution time traces.

Paano i-test ang app para sa pag-freeze?

Gumamit ng UI tests na may check na ang screen ay nagbubukas sa loob ng mas mababa sa 1 segundo. Magdagdag sa CI ng pagsukat ng oras sa pagitan ng pagpindot at paglitaw ng susunod na screen. Sa Android, gamitin ang Espresso na may IdlingResource para maghintay ng asynchronous operations. Sa iOS, XCTest na may XCTWaiter para suriin ang oras ng pag-load.

Maaari bang magdulot ng pag-freeze ang SwiftUI?

SwiftUI mismo ay hindi nagdudulot ng pag-freeze, ngunit ang mga kumplikadong computation sa body property — oo. Kung ang body ay nagko-compute nang 500 ms dahil sa mabibigat na operasyon, nag-freeze ang UI. Solusyon — ilipat ang computations sa Task.detached at i-update ang @State nang asynchronously sa main actor.

Buod

  • Pag-freeze — kumpletong pag-block ng UI sa loob ng mga segundo at sampung segundo, sanhi ng pag-block ng main thread, deadlock o walang katapusang loop
  • Diagnosis — /data/anr/traces.txt sa Android, Stackshot at Main Thread Checker sa iOS
  • Mga pangunahing dahilan — synchronous I/O, deadlock sa pagitan ng threads, walang katapusang recursion, mahabang GC
  • Pagtanggal — coroutines na may tamang dispatcher, async/await na may MainActor, paglipat ng lahat ng IO operations sa background threads
  • Pag-iwas — StrictMode na may penaltyDeath, Main Thread Checker, static analysis ng deadlock (Infer, TSAN)
  • Sa Android pag-freeze > 5 s = ANR; sa iOS > 10–20 s = Watchdog crash (0x8badf00d)
  • Rekomendasyon: i-on ang Thread Sanitizer sa Debug schema at i-configure ang CI para magpatakbo ng mga test na may TSAN para matukoy ang data race at deadlock

Gagawa kami ng mobile application na turnkey

Gumagawa ang IT Sectr ng mga iOS at Android application para sa mga startup at negosyo mula noong 2017. Magpapayo kami sa iyo at magmumungkahi ng pinakamahusay na solusyon.

Pag-usapan ang proyekto

Basahin din