Əlaqənin itirilməsi — mobil tətbiqlərdə ən çox rast gəlinən və ən qıcıqlandırıcı hadisələrdən biridir. İstifadəçi məlumatlara girişini itirir, əməliyyat dayanır, tətbiq donur və ya çökür. Google Android Developer Blog məlumatına görə, istifadəçilərin 70%-i tətbiq iki dəfə çökərsə və ya donarsa onu silir. Əlaqə itkisinin səbəblərini və dayanıqlı kommunikasiya qurmaq üsullarını nəzərdən keçirək.
Əsas məqamlar
Qopur — istifadəçi terminidir, tətbiqin serverlə əlaqəni itirməsi, hərəkətlərə cavab verməməsi və ya xəta ilə bitməsi vəziyyətini təsvir edir. Texniki mənada bu ola bilər: şəbəkə xətası (timeout, DNS failure), ANR (UI axınının bloklanması), crash (idarə olunmayan istisna) və ya race condition (yarış vəziyyəti).
İstifadəçi üçün bütün bu ssenarilər eyni görünür: tətbiq işləməyi dayandırır. Tərtibatçı üçün fərq diaqnostika və düzəltmə yanaşmasındadır. Şəbəkə xətaları retry mexanizmləri ilə, ANR — əməliyyatların UI axınından çıxarılması ilə, crash — istisnaların idarə edilməsi ilə həll olunur.
Crittercism (indiki Apteligent) məlumatına görə, orta mobil tətbiq hər çöküşdə istifadəçilərin 1-2%-ni itirir. 1 milyon istifadəçisi olan tətbiq üçün bu, bir xətaya 10-20 min itirilmiş quraşdırma deməkdir. Bu, xüsusilə maliyyə və tibb sektorundakı tətbiqlər üçün kritikdir.
Qeyri-sabit şəbəkə — mobil cihazlar daim Wi-Fi və mobil şəbəkə arasında keçid edir, əhatə dairəsi olmayan zonalara (metro, lift, zirzəmi) daxil olur. Hər keçid müvəqqəti əlaqə itkisinə səbəb olur və tətbiq bunu düzgün idarə etməlidir.
Timeoutlar — server müəyyən edilmiş vaxtda (adətən 10-30 saniyə) cavab vermirsə, müştəri SocketTimeoutException atır. Uzun timeoutlar geribildirimsiz istifadəçi tərəfindən donma kimi qəbul edilir. Timeoutun 15 saniyədən çox olmaması tövsiyə olunur.
val client = OkHttpClient.Builder()
.connectTimeout(10, TimeUnit.SECONDS)
.readTimeout(15, TimeUnit.SECONDS)
.writeTimeout(15, TimeUnit.SECONDS)
.retryOnConnectionFailure(true)
.build()
Yarış vəziyyəti (race condition) — bir neçə axının sinxronizasiya olmadan eyni məlumatları eyni anda oxuyub yazması zamanı yaranır. Məsələn, UI axınında keşdən məlumatların yüklənməsi paralel olaraq şəbəkədən keşin yenilənməsi ilə köhnəlmiş və ya səhv məlumatların göstərilməsinə səbəb ola bilər.
Offline-first — yerli yaddaşın (Room, CoreData) yeganə həqiqət mənbəyi olduğu arxitektura nümunəsi. Şəbəkə fon məlumatlarının sinxronizasiyası üçün istifadə olunur. İstifadəçi şəbəkə olmadıqda belə yerli keşdən aktual məlumatları görür.
Repository pattern — məlumatlar üçün vahid giriş nöqtəsi, məlumatların şəbəkədən və ya keşdən götürüləcəyinə qərar verir. Repozitoriya məlumat mənbəyini ViewModel və UI-dən abstraksiya edir. Şəbəkə xətası zamanı repozitoriya avtomatik olaraq yerli mənbəyə keçir.
class UserRepository(
private val api: UserApi,
private val dao: UserDao
) {
suspend fun getUsers(): Result<List<User>> {
return try {
val remote = api.fetchUsers()
dao.insertAll(remote)
Result.success(remote)
} catch (e: IOException) {
val cached = dao.getAll()
if (cached.isNotEmpty()) {
Result.success(cached) // şəbəkə xətasında keşi qaytar
} else {
Result.failure(e)
}
}
}
}
Circuit Breaker — serverin əlçatmaz olduqda sorğu selindən qorunması nümunəsi. Ardıcıl N xətadan sonra açar açılır və bütün sorğular əlaqə cəhdi olmadan dərhal xəta qaytarır. Müəyyən vaxtdan sonra açar sınaq sorğusu üçün yarıaçıq vəziyyətə keçir.
Exponential backoff — standart retry mexanizmi. İlk uğursuzluqdan sonra 1 saniyə, ikincidən sonra 2 saniyə, sonra 4, 8, 16 gözləyin. Maksimum cəhd sayını məhdudlaşdırın (adətən 3-5), serveri və batareyanı həddən artıq yükləməmək üçün.
İstifadəçi geribildirimi — şəbəkə xətası zamanı anlaşılan mesaj göstərin: "Əlaqə yoxdur", "Server müvəqqəti əlçatmazdır", "İnterneti yoxlayın". Snackbar və ya Inline State View istifadə edin. Heç vaxt istifadəçiyə texniki xətaları (HTTP 500, SocketException) göstərməyin.
ConnectivityManager — şəbəkəni izləmək üçün Android API. Tətbiqə dəyişikliklərə reaksiya verməyə imkan verin: şəbəkə itkisində placeholder göstərin, bərpa zamanı avtomatik məlumatları yeniləyin. iOS-da Network framework-dən NWPathMonitor istifadə edin.
class NetworkMonitor(private val context: Context) {
private val manager =
context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
fun isOnline(): Boolean {
val network = manager.activeNetwork ?: return false
val caps = manager.getNetworkCapabilities(network) ?: return false
return caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
}
}
Crashlytics (Firebase) — mobil tətbiqlər üçün standart çöküş hesabatı aləti. Bütün idarə olunmayan istisnaların stacktrace-nı, OS versiyasını, cihaz modelini və çöküş vaxtını toplayır. Xətaları qruplaşdırmağa və düzəlişlərə cavabdehlər təyin etməyə imkan verir.
Sentry — performans monitorinqi dəstəyi ilə Crashlytics-ə alternativ. Müəyyən əməliyyatları (məsələn, "istifadəçinin avtorizasiyası") izləməyə və xətanın hansı mərhələdə baş verdiyini görməyə imkan verir. Performance tracing şəbəkə timeoutlarını tətbiq məntiqindəki səhvlərdən ayırmağa kömək edir.
Timber — Android üçün sinifə görə avtomatik teqlər əlavə edən loqlama kitabxanası. Debug quruluşunda bütün şəbəkə sorğularını və cavablarını loqlayın. Release quruluşunda — yalnız Crashlytics.setCustomLog vasitəsilə xəta və xəbərdarlıqları loqlayın.
| Alət | Tip | Nə vaxt istifadə etməli |
|---|---|---|
| Crashlytics | Crash reporting | Həmişə release-də — çöküşlərin avtomatik toplanması |
| Sentry | Crash + Performance | Müəyyən istifadəçi ssenarilərini profilləşdirmək lazım olduqda |
| Timber | Logging | Debug: tam loqlama; Release: yalnız xətalar |
| HTTP Toolkit | Network debug | HTTP trafikinin lokal ələ keçirilməsi və analizi |
Firebase Summit 2023 məlumatına görə, Crashlytics + Performance Monitoring tətbiq edən tətbiqlər kritik səhvlərin aşkarlanması və düzəldilməsinin orta vaxtını 3 gündən 4 saata endirir. Aktiv istifadəçilərin 0.1%-dən çox tezliyi olan hər çöküşə alertlər qurmaq tövsiyə olunur.
Tez-tez verilən suallar
Əgər crash Crashlytics-də tutulmursa, native crash (SIGSEGV, SIGABRT) yoxlayın — onlar Java/Kotlin exception handler tərəfindən işlənmir. Android-də bu JNI-dən native yaddaş sızması, iOS-da EXC_BAD_ACCESS ola bilər. Native crash stacktrace toplamaq üçün Breakpad (Android) və ya PLCrashReporter (iOS) istifadə edin.
Network Link Conditioner (iOS-da quraşdırılmış, Android üçün Facebook Network Connection Class və ya Developer Options > Network > Select network type) istifadə edin. Gecikməni 500-3000 ms və paket itkisini 5-30% təyin edin. Həmçinin şəbəkə gecikmələrini və qopmalarını simulyasiya etmək üçün Charles Proxy və ya mitmproxy istifadə edə bilərsiniz.
ANR UI axını 5 saniyədən çox bloklandıqda yaranır. Şəbəkə sorğuları fon axınında yerinə yetirilməlidir: coroutines (viewModelScope.launch(Dispatchers.IO)), RxJava (subscribeOn(Schedulers.io)) və ya sinxronizasiya üçün WorkManager. HTTP müştərisində həmişə timeoutlar təyin edin — timeoutun olmaması sonsuz blokadaya səbəb ola bilər.
Race condition — əməliyyatın nəticəsinin axınların icra ardıcıllığından asılı olduğu vəziyyət. Məsələn, istifadəçi "Göndər" düyməsini iki dəfə sürətlə basır və sorğu iki dəfə gedir. Həlli: Mutex, single-threaded executors və ya state machine istifadə edin (düyməni ilk basışdan sonra söndürün). Kotlin-də coroutines-dən Mutex və ya @Synchronized annotasiyasından istifadə edin.
Mobil tətbiqlər üçün Chaos Engineering tətbiq edin: əməliyyatlar zamanı şəbəkəni söndürün, yüksək gecikmə simulyasiya edin, Wi-Fi və mobil şəbəkə arasında keçid edin, prosesi sistem tərəfindən öldürün. Alətlər: Facebook Network Connection Class, Charles Proxy, iOS Network Link Conditioner. CI/CD-də AndroidTest Orchestrator vasitəsilə müxtəlif şəbəkə şərtləri ilə UI testləri əlavə edin.
Nəticə
Açar təslim mobil tətbiq hazırlayacağıq
IT Sectr 2017-ci ildən startaplar və bizneslər üçün iOS və Android tətbiqləri yaradır. Sizə məsləhət verəcəyik və ən yaxşı həlli təklif edəcəyik.
Həm də oxuyun