Donma (takılma), mobil uygulamanın uzun süre boyunca kullanıcının hiçbir eylemine yanıt vermemesi durumudur. Lag (yavaşlama) ve glitch (hatalı davranış)tan farklı olarak donma, UI'yı tamamen bloke eder: dokunuşlar işlenmez, animasyon durur, ekran “donar”. Nedeni, ana iş parçacığının senkron bir işlem tarafından bloke edilmesi, çok iş parçacıklı kodda deadlock veya anormal derecede uzun çöp toplamadır. Apple Main Thread Checker Dokümantasyonu'na göre, iOS crash raporlarının %40'ından fazlası ana iş parçacığı blokajıyla ilgilidir. Android'de benzer bir durum ANR'ye — sistem diyaloğu “Uygulama yanıt vermiyor” — yol açar.
Ana Hatlar
Donma (takılma), mobil uygulamada uygulamanın birkaç saniye veya daha uzun süre giriş olaylarını işlemeyi ve arayüzü güncellemeyi durdurması durumudur. Teknik olarak bu, ana iş parçacığının bloke olduğu ve bir sonraki çalıştırma döngüsü yinelemesini gerçekleştiremediği anlamına gelir.
Lag, kullanıcının yavaşlama fark ettiği ancak uygulamanın çalışmaya devam ettiği 500 ms'ye kadar olan gecikmedir. Donma 1 saniyeden onlarca saniyeye kadar sürer. Android'de ANR, 5 saniyeden uzun süren ve sistem tarafından tespit edilen özel bir donma durumudur. Her donma ANR'ye yol açmaz, ancak her ANR sistem tarafından belgelenmiş bir donmadır.
Android'te, 5 saniyeden uzun süren donma, uygulamayı kapatmayı öneren bir ANR diyaloğu tetikler. iOS'ta, sistemin bir watchdog'u vardır — uygulama 10–20 saniye boyunca olaylara yanıt vermezse, Watchdog işlemi 0x8badf00d (ate bad food) koduyla sonlandırır. Kullanıcı yalnızca uygulamanın aniden ana ekrana kapanmasını görür.
100 ms'den uzun süren ve ana iş parçacığında başlatılan herhangi bir işlem potansiyel olarak donmaya neden olabilir. Blokajların ana kaynaklarına bakalım.
Büyük bir dosya okumak, eşzamansızlık olmadan ağ isteği, senkron apply yöntemi ve ardından commit ile SharedPreferences'a veri kaydetmek — tüm bu işlemler ana iş parçacığını bloke eder. Android'te, 10 MB'lık bir dosyayı senkron okumak, flash bellek hızına bağlı olarak 200–500 ms sürebilir. iOS'ta, completionHandler olmadan senkron URLSession yüklemesi, sunucu yanıt süresi boyunca UI'yı bloke eder.
İki iş parçacığı birbirinin tuttuğu kaynakları beklediğinde deadlock oluşur. Mobil uygulamalarda tipik senaryo, A iş parçacığının Lock1'i kilitleyip Lock2'yi beklemesi, B iş parçacığının ise Lock2'yi kilitleyip Lock1'i beklemesidir. Her iki iş parçacığı da sonsuza kadar donar. Bunlardan biri ana iş parçacığıysa, uygulama tamamen donar.
Bir mantık hatası — örneğin, çıkış koşulu olmayan while(true) veya temel durumu olmayan özyineleme — ana iş parçacığında sonsuz yürütmeye yol açar. Android bunu 5 saniye sonra ANR ile tespit eder, iOS — sonsuz tekrarlanan çağrı yığınını yakalayan Stackshot ile tespit eder.
Donma teşhisi, blokaj anında tüm iş parçacıklarının durumunu yakalayabilen araçlar gerektirir.
Her ANR'de, Android sistemi her uygulama iş parçacığının yığın dökümünü içeren bir dosya /data/anr/traces.txt kaydeder. Bu dosyayı analiz etmek ana teşhis yöntemidir: main iş parçacığını bulun ve hangi yöntemde durduğunu görün. Yığın Thread.sleep, InputStream.read veya Lock.lock ile bitiyorsa — neden bulunmuştur.
Xcode, uygulama donduğunda (SIGSTOP sinyali) bir Stackshot — tüm iş parçacığı yığınlarının anlık görüntüsü — alabilir. Şemada “Logging” → “Include Stackshot Logs” seçeneğini etkinleştirin. 0x8badf00d koduyla çökme durumunda, Devices & Simulators'dan crash günlüğünü çıkarın ve sıkışmış yığınla com.apple.main-thread'i bulun.
Main Thread Checker, uygulama çalışırken arka plan iş parçacıklarından UIKit çağrılarını otomatik olarak algılar. Şemada etkinleştirin (Diagnostics → Main Thread Checker). Her uyarı, özellikle bir ağ isteği completionHandler closure'ında meydana gelirse, donmanın potansiyel bir nedenidir.
Android'de StrictMode ile blokaj tespiti örneği:
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())
}
}
Donmaları giderme, potansiyel olarak uzun tüm işlemleri arka plan iş parçacıklarına taşımakla başlar. Her platform için belirli tekniklere bakalım.
Kotlin Coroutines viewModelScope.launch(Dispatchers.IO) ile ağ işlemlerinin veya veritabanı okumalarının arka plan iş parçacığında yürütülmesini sağlar. Dispatchers.Main yalnızca UI güncellemeleri için kullanılır. Önemli: tüm suspend işlevleri yapılandırılmış olmalıdır — alt coroutine'ler üst iptal edildiğinde iptal edilir, iş parçacığı sızıntılarını önler.
Grand Central Dispatch arka plan görevleri için DispatchQueue.global(qos: .userInitiated) ve UI güncellemeleri için DispatchQueue.main.async ile standart desendir. Ana kuyrukta sync()'ten kaçının — bu garantili bir deadlock'tur. MainActor aracılığıyla ana iş parçacığına otomatik dönüşle daha okunabilir zaman uyumsuz kod için async/await (Swift 5.5+) kullanın.
Ana iş parçacığında Kotlin'de synchronized blokları ve Swift'te @synchronized tehlikelidir: başka bir iş parçacığı bu kilidi zaten almışsa, ana iş parçacığı beklerken donar. Kilitler yerine atomik türler (AtomicInteger, Swift'te atomik özellikler) veya sıralı kuyruklar kullanın.
Android'de coroutine ile zaman uyumsuz veri yükleme örneği:
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)
}
}
}
Araçlar, mimari ilkeler ve kod inceleme süreçlerinin bir kombinasyonu, donmaları sistematik olarak önlemeye yardımcı olur.
İş parçacığı politikaları için StrictMode'u penaltyDeath ile yapılandırın — bu, ana iş parçacığında bir ağ çağrısı veya disk G/Ç tespit edildiğinde uygulamanın anında çökmesine neden olur. Geliştirici sorunu görmezden gelemez. Üretim yapılarında, çökme olmadan istatistik toplamak için penaltyLog kullanın.
iOS'ta, Debug şemasında Main Thread Checker'ı etkinleştirin ve CI'yi bu seçenekle testleri çalıştıracak şekilde yapılandırın. Bir test, arka plan iş parçacığından bir UIKit çağrısı içeriyorsa — başarısız olmalıdır. TestFlight'a göndermeden önce sorunu belirlemenin tek güvenilir yolu budur.
Kod inceleme sürecine zorunlu bir madde ekleyin: herhangi bir ağ çağrısı, dosya işlemi, veritabanı erişimi veya ağır hesaplamanın arka plan iş parçacığında çalıştığını kontrol edin. Deadlock, statik analizörlerle tespit edilebilir: Facebook'tan Infer ve Xcode'dan Thread Safety Checker, çalışma zamanından önce potansiyel kilitleri bulur.
Sıkça Sorulan Sorular
ANR (Application Not Responding), ana iş parçacığı 5 saniyeden fazla donduğunda görünen bir Android sistem bildirimidir. Donma daha geniş bir kavramdır: herhangi bir süredeki herhangi bir UI blokajı. iOS'ta ANR yoktur, ancak 10–20 saniye zaman aşımlı bir Watchdog vardır.
Dosya /data/anr/traces.txt konumundadır. Erişim için root erişimi veya adb shell gerekir: root yetkileriyle adb shell cat /data/anr/traces.txt \> traces.txt komutunu çalıştırın. Yığında “main” iş parçacığını bulun — son çağrılan yöntem blokajın nedenini gösterir.
Donma 10 saniyeden az sürerse, Watchdog tetiklenmez ve uygulama bloke eden işlem tamamlanana kadar “takılı kalır”. Kullanıcı çökme görmez ancak hayal kırıklığı yaşar. Bu tür durumları tespit etmek için, özel yürütme süresi izleriyle MetricKit kullanın.
Ekranın 1 saniyeden kısa sürede açıldığını kontrol eden UI testleri kullanın. Dokunma ile sonraki ekranın görünmesi arasındaki süre ölçümünü CI'ya ekleyin. Android'te, zaman uyumsuz işlemleri beklemek için IdlingResource ile Espresso kullanın. iOS'ta, yükleme süresini kontrol etmek için XCTWaiter ile XCTest kullanın.
SwiftUI kendisi donmalara neden olmaz, ancak body özelliğindeki karmaşık hesaplamalar neden olur. Ağır işlemler nedeniyle body hesaplaması 500 ms sürerse, UI donar. Çözüm, hesaplamaları Task.detached'a aktarmak ve @State'i ana aktörde zaman uyumsuz olarak güncellemektir.
Özet
Anahtar teslim bir mobil uygulama geliştireceğiz
IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.
Ayrıca okuyun