Pembekuan (visnet) — adalah kondisi di mana aplikasi seluler berhenti merespons tindakan pengguna untuk waktu yang lama. Berbeda dengan lag (perlambatan) dan glitch (perilaku salah), pembekuan sepenuhnya memblokir UI: sentuhan tidak diproses, animasi berhenti, layar „membeku". Penyebabnya — pemblokiran thread utama oleh operasi sinkron, deadlock dalam kode multi-thread, atau pengumpulan sampah yang sangat lama. Menurut Apple Main Thread Checker Documentation, lebih dari 40% laporan crash di iOS terkait dengan pemblokiran thread utama. Di Android, situasi serupa menyebabkan ANR — dialog sistem „Aplikasi tidak merespons".
Poin utama
Pembekuan (freeze, hang) dalam aplikasi seluler — adalah kondisi di mana aplikasi berhenti memproses peristiwa input dan memperbarui antarmuka selama beberapa detik atau lebih. Secara teknis ini berarti thread utama (main thread) diblokir dan tidak dapat menjalankan siklus runner berikutnya.
Lag — adalah keterlambatan hingga 500 ms, di mana pengguna melihat perlambatan, tetapi aplikasi terus berfungsi. Pembekuan berlangsung dari 1 detik hingga puluhan detik. ANR di Android — adalah kasus khusus pembekuan yang berlangsung lebih dari 5 detik dan terdeteksi oleh sistem. Tidak setiap pembekuan menyebabkan ANR, tetapi setiap ANR adalah pembekuan yang didokumentasikan oleh sistem.
Di Android, pembekuan lebih dari 5 detik memicu dialog ANR dengan saran untuk menutup aplikasi. Di iOS, sistem memiliki watchdog — jika aplikasi tidak merespons peristiwa dalam 10–20 detik, Watchdog menghentikan proses dengan kode 0x8badf00d (ate bad food). Pengguna hanya melihat penutupan mendadak aplikasi dan kembali ke layar utama.
Setiap operasi yang berlangsung lebih dari 100 ms dan dijalankan di thread utama berpotensi menyebabkan pembekuan. Mari kita lihat sumber utama pemblokiran.
Membaca file besar, permintaan jaringan tanpa asinkron, menyimpan data di SharedPreferences dengan metode sinkron apply diikuti commit — semua operasi ini memblokir thread utama. Di Android, pembacaan sinkron file 10 MB dapat memakan waktu 200–500 ms tergantung pada kecepatan memori flash. Di iOS, pemuatan sinkron URLSession tanpa completionHandler memblokir UI selama waktu respons server.
Ketika dua thread menunggu pelepasan sumber daya yang dipegang satu sama lain, terjadi deadlock. Dalam aplikasi seluler, skenario tipikal — thread A memblokir Lock1 dan menunggu Lock2, sementara thread B memblokir Lock2 dan menunggu Lock1. Kedua thread membeku selamanya. Jika salah satunya adalah thread utama, aplikasi membeku sepenuhnya.
Kesalahan logika — misalnya while(true) tanpa kondisi keluar atau rekursi tanpa kasus dasar — menyebabkan eksekusi tak terbatas di thread utama. Android mendeteksi ini melalui ANR setelah 5 detik, iOS — melalui Stackshot, yang merekam tumpukan panggilan yang berulang tak terbatas.
Diagnostik pembekuan memerlukan alat yang dapat merekam keadaan semua thread pada saat pemblokiran.
Setiap ANR, sistem Android menyimpan file /data/anr/traces.txt, yang berisi dump tumpukan setiap thread aplikasi. Analisis file ini — metode diagnostik utama: temukan thread main dan lihat metode mana yang dihentikan. Jika tumpukan berakhir dengan Thread.sleep, InputStream.read, atau Lock.lock — penyebabnya ditemukan.
Xcode saat aplikasi membeku (sinyal SIGSTOP) dapat mengambil Stackshot — snapshot tumpukan semua thread. Aktifkan di skema „Logging" → „Include Stackshot Logs". Saat crash dengan kode 0x8badf00d, ekstrak log crash dari Devices & Simulators dan temukan thread com.apple.main-thread dengan tumpukan beku.
Main Thread Checker secara otomatis mendeteksi panggilan UIKit dari thread latar belakang selama aplikasi berjalan. Aktifkan di skema (Diagnostics → Main Thread Checker). Setiap peringatan adalah potensi penyebab pembekuan, terutama jika terjadi di penutupan completionHandler permintaan jaringan.
Contoh deteksi pemblokiran melalui StrictMode di Android:
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())
}
}
Perbaikan pembekuan dimulai dengan memindahkan semua operasi yang berpotensi lama ke thread latar belakang. Mari kita lihat teknik spesifik untuk setiap platform.
Kotlin Coroutines dengan viewModelScope.launch(Dispatchers.IO) memastikan bahwa operasi jaringan atau pembacaan basis data dijalankan di thread latar belakang. Dispatchers.Main hanya digunakan untuk memperbarui UI. Penting: semua fungsi suspend harus terstruktur — coroutine anak dibatalkan saat induk dibatalkan, mencegah kebocoran thread.
Grand Central Dispatch dengan DispatchQueue.global(qos: .userInitiated) untuk tugas latar belakang dan DispatchQueue.main.async untuk pembaruan UI — pola standar. Hindari sync() di antrean utama — ini deadlock yang terjamin. Gunakan async/await (Swift 5.5+) untuk kode asinkron yang lebih mudah dibaca dengan pengembalian otomatis ke thread utama melalui MainActor.
Blok synchronized di Kotlin dan @synchronized di Swift di thread utama berbahaya: jika thread lain telah mengambil kunci ini, thread utama akan membeku menunggu. Gunakan tipe atomik (AtomicInteger, properti atomik di Swift) atau antrean sekuensial alih-alih kunci.
Contoh pemuatan data asinkron dengan coroutine di Android:
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)
}
}
}
Mencegah pembekuan secara sistematis membantu kombinasi alat, prinsip arsitektur, dan proses tinjauan kode.
Konfigurasikan StrictMode dengan penaltyDeath untuk kebijakan thread — ini akan menyebabkan aplikasi langsung crash saat mendeteksi panggilan jaringan atau I/O disk di thread utama. Pengembang tidak dapat mengabaikan masalah. Di build produksi, gunakan penaltyLog untuk mengumpulkan statistik tanpa crash.
Di iOS, aktifkan Main Thread Checker di skema Debug dan konfigurasikan CI untuk menjalankan tes dengan opsi ini. Jika tes berisi panggilan UIKit dari thread latar belakang — harus gagal. Ini adalah satu-satunya cara yang dapat diandalkan untuk mendeteksi masalah sebelum dikirim ke TestFlight.
Tambahkan ke proses tinjauan kode poin wajib: periksa bahwa setiap panggilan jaringan, pekerjaan file, basis data, atau perhitungan berat dijalankan di thread latar belakang. Deadlock dapat dideteksi dengan penganalisis statis: Infer dari Facebook dan Thread Safety Checker dari Xcode menemukan potensi pemblokiran sebelum dijalankan.
Pertanyaan yang sering diajukan
ANR (Application Not Responding) — pemberitahuan sistem Android yang muncul saat thread utama membeku lebih dari 5 detik. Pembekuan adalah konsep yang lebih luas: setiap pemblokiran UI dengan durasi berapa pun. Di iOS tidak ada ANR, tetapi ada Watchdog dengan batas waktu 10–20 detik.
File terletak di /data/anr/traces.txt. Untuk akses diperlukan root atau adb shell: jalankan adb shell cat /data/anr/traces.txt \> traces.txt dengan hak root. Dalam tumpukan, temukan thread „main" — metode yang terakhir dipanggil menunjukkan penyebab pemblokiran.
Jika pembekuan berlangsung kurang dari 10 detik, Watchdog tidak aktif, dan aplikasi hanya „membeku" hingga operasi pemblokiran selesai. Pengguna tidak melihat crash, tetapi mengalami frustrasi. Untuk mendeteksi kasus seperti itu, gunakan MetricKit dengan pelacakan waktu eksekusi kustom.
Gunakan tes UI dengan memeriksa bahwa layar terbuka dalam waktu kurang dari 1 detik. Tambahkan ke CI pengukuran waktu antara sentuhan dan munculnya layar berikutnya. Di Android, gunakan Espresso dengan IdlingResource untuk menunggu operasi asinkron. Di iOS, XCTest dengan XCTWaiter untuk memeriksa waktu muat.
SwiftUI sendiri tidak menyebabkan pembekuan, tetapi perhitungan kompleks di properti body — ya. Jika body dihitung selama 500 ms karena operasi berat, UI membeku. Solusi — pindahkan perhitungan ke Task.detached dan perbarui @State secara asinkron di aktor utama.
Ringkasan
Kami akan mengembangkan aplikasi seluler turnkey
IT Sectr membuat aplikasi iOS dan Android untuk startup dan bisnis sejak 2017. Kami akan memberi saran dan mengusulkan solusi terbaik.
Baca juga