Observer — davranış nümunəsi, burada bir obyekt (naşir) vəziyyətinin dəyişməsi barədə çoxsaylı abunəçiləri xəbərdar edir. Mobil inkişafda Observer reaktiv mexanikanın əsasını təşkil edir: UI verilənlər dəyişikliklərinə abunə olur və avtomatik yenilənir. Nümunə iOS-da NotificationCenter və Android-də LiveData/Flow vasitəsilə həyata keçirilir. Ətraflı — Refactoring Guru: Observer.
Əsas məqamlar
Observer (müşahidəçi) — obyektlər arasında «birə çox» asılılığını təyin edən GoF davranış nümunəsi. Bir obyekt (Subject və ya Observable) vəziyyətini dəyişdikdə, bütün asılı obyektlər (Observers) avtomatik xəbərdar edilir və yenilənir. Nümunə zəif bağlantını həyata keçirir: naşir abunəçilərin konkret siniflərini bilmir — yalnız onların Observer interfeysini tətbiq etdiyini bilir.
Observer strukturu attach(), detach(), notify() metodları ilə Subject interfeysini və update() metodu ilə Observer interfeysini əhatə edir. ConcreteSubject vəziyyəti və abunəçilər siyahısını saxlayır. ConcreteObserver update()-i tətbiq edir və dəyişikliklərə reaksiya verir. Mobil inkişafda GoF-ün klassik tətbiqi nadir hallarda olur — onu daxili mexanizmlər əvəz edir: NotificationCenter, Combine, Flow, LiveData, eyni ideyanı müasir API ilə həyata keçirir.
Push vs Pull modeli — Push modelində Subject verilənləri bütün abunəçilərə göndərir (NotificationCenter.post). Pull modelində Subject yalnız xəbərdar edir, abunəçi isə verilənləri özü əldə edir. Android LiveData Push-dan istifadə edir (verilənlər observe()-də ötürülür), RxJava/Flow hər iki modeli dəstəkləyir. Seçim tapşırıqdan asılıdır: Push UI yeniləmələri üçün daha sadədir, Pull abunəçinin almaq istəmədiyi böyük həcmli verilənlər üçün daha səmərəlidir.
NotificationCenter — Observer-i tətbiq etmək üçün iOS/macOS-un daxili mexanizmi. Naşir Notification-i NotificationCenter.default.post(name:, object:, userInfo:) vasitəsilə göndərir. Abunəçi addObserver(forName:, queue:, using:) vasitəsilə qeydiyyatdan keçir. NotificationCenter adlandırılmış xəbərdarlıqları (Notification.Name) dəstəkləyir və userInfo-da istənilən veriləni ötürə bilər. UIKeyboardWillShowNotification, UIApplicationDidEnterBackgroundNotification — sistem nümunələri.
extension Notification.Name {
static let userDidLogin = Notification.Name("userDidLogin")
}
// Naşir
NotificationCenter.default.post(
name: .userDidLogin,
object: nil,
userInfo: ["userId": "123"]
)
// Abunəçi
class ProfileViewModel {
private var observers: [NSObjectProtocol] = []
func startObserving() {
let observer = NotificationCenter.default.addObserver(
forName: .userDidLogin,
object: nil,
queue: .main
) { [weak self] notification in
guard let userId = notification.userInfo?["userId"] as? String else { return }
// Abunəçi hadisəyə reaksiya verir
self?.loadProfile(userId: userId)
}
observers.append(observer)
}
func stopObserving() {
observers.forEach { NotificationCenter.default.removeObserver($0) }
observers.removeAll()
}
}
Combine framework — iOS 13-dən etibarən NotificationCenter-ə müasir reaktiv alternativ. Publisher (NotificationCenter, URLSession.Timer) — naşir, Subscriber (sink, assign) — abunəçi. Combine verilən axınını transformasiya etmək üçün operatorlar (map, filter, combineLatest) əlavə edir. @Published — abunəçiləri dəyişikliklər barədə avtomatik xəbərdar edən property wrapper. SwiftUI ilə MVVM-də Combine ViewModel və View-i birləşdirmək üçün NotificationCenter-i əvəz edir.
KVO (Key-Value Observing) — obyektlərin ayrı-ayrı xüsusiyyətlərini izləmək üçün köhnə ObjC/Swift mexanizmi. @objc dynamic var name: String — müşahidə olunan xüsusiyyət. observe(.name) — abunəlik. KVO yalnız @objc-uyğun siniflər və ObjC irsi ilə işləyir. Apple yeni layihələrdə KVO əvəzinə Combine və @Published tövsiyə edir. KVO hibrid layihələrdə UIKit uyğunluğu üçün aktual olaraq qalır.
LiveData — Observer-i tətbiq etmək üçün Android Architecture Components komponenti. Verilənlər dəyişiklikləri barədə abunəçiləri xəbərdar edən Observable sinfi. LiveData həyat dövrünü nəzərə alır: abunəçilər (LifecycleOwner) məhv edildikdə avtomatik abunəni ləğv edir. LiveData Push modelidir: verilənlər observe()-də ötürülür. LiveData Jetpack Compose-un tətbiqinə qədər Android-də MVVM-nin əsas tikinti blokudur.
// ViewModel — naşir
class UserViewModel : ViewModel() {
private val _user = MutableLiveData<User?>(null)
val user: LiveData<User?> = _user
fun loadUser(id: String) {
viewModelScope.launch {
val result = userRepository.getUser(id)
_user.value = result
}
}
}
// Fragment — abunəçi
class UserFragment : Fragment() {
private val viewModel: UserViewModel by viewModels()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
viewModel.user.observe(viewLifecycleOwner) { user ->
// Abunəçi dəyişikliklərə reaksiya verir
userName.text = user?.name
userEmail.text = user?.email
}
}
}
StateFlow və SharedFlow — Jetpack Compose-da LiveData-nı əvəz edən Kotlin Coroutines-dən reaktiv tiplər. StateFlow — sabit cari dəyəri olan müşahidə edilə bilən state holder. SharedFlow — vəziyyətsiz konfiqurasiya edilə bilən hot flow, birdəfəlik hadisələr (naviqasiya, tostlar) üçün uyğundur. Hər iki tip Compose ilə sıx inteqrasiya olunub: collectAsState(), collectAsEffect(). StateFlow Compose ilə müasir Android layihələrində məcburidir.
LiveData vs StateFlow — LiveData Android Lifecycle-ə bağlıdır, StateFlow platformadan asılı deyil. StateFlow coroutines, operatorları (map, filter) dəstəkləyir və Android asılılıqları olmadan test edilir. LiveData Java uyğunluğu üçün daha sadədir. Google Kotlin + Compose ilə yeni layihələr üçün StateFlow, köhnə layihələr və ya Java kodu üçün LiveData tövsiyə edir.
Yaddaş sızmaları (memory leaks) — abunəliklərin düzgün idarə edilməməsi ilə Observer-in əsas problemi. Abunəçi (Activity, Fragment, UIViewController) məhv edilibsə, lakin abunəni ləğv etməyibsə, naşir ona istinadı saxlamağa davam edir və garbage collector yaddaşı boşalda bilmir. Android-də LifecycleOwner (Activity/Fragment) removeObserver() çağırmalı və ya observe(viewLifecycleOwner) istifadə etməlidir. iOS-da — deinit-də removeObserver və ya Combine-də disposeBag.
| Platforma | Observer mexanizmi | Avtomatik abunə ləğvi | Əl ilə abunə ləğvi |
|---|---|---|---|
| iOS | NotificationCenter | Xeyr | deinit-də removeObserver() |
| iOS | Combine (sink) | Xeyr | store(in: &bag) — DisposeBag |
| iOS | KVO | Xeyr | deinit-də removeObserver() |
| Android | LiveData | Bəli (LifecycleOwner) | removeObserver() isteğe bağlı |
| Android | StateFlow | viewModelScope vasitəsilə | Abunə ləğvində cancel() Job |
| Android | RxJava | Xeyr | CompositeDisposable-da dispose() |
Abunəçilərdə zəif istinad (weak reference) — abunə blokunda Swift-də [weak self] istifadə edin və Kotlin-də lifecycle scope-a istinad edin. LiveData abunəliyi LifecycleOwner vasitəsilə avtomatik idarə edir — abunəlik yalnız Lifecycle STARTED və ya RESUMED vəziyyətində olduqda aktivdir. Compose-da StateFlow lifecycle nəzərə alınmaqla collectAsState() istifadə edir. iOS-da NotificationCenter açıq [weak self] tələb edir, çünki closure self-ə güclü istinad edir.
Observer (GoF) və Publisher-Subscriber (PubSub) — oxşar, lakin fərqli nümunələr. Observer-də naşir abunəçiləri birbaşa onların metodlarını çağıraraq xəbərdar edir. Naşir abunəçilər haqqında bilir (siyahı saxlayır). PubSub-da naşir və abunəçi bir-biri haqqında bilmir — onların arasında vasitəçi (Event Bus, Message Queue, NotificationCenter) var. Naşir kanala mesaj göndərir, abunəçi kanalı dinləyir. PubSub daha zəif bağlantı təmin edir.
Mobil inkişafda PubSub nümunələri — iOS-da NotificationCenter PubSub hesab edilə bilər: naşir abunəçiləri tanımır — sadəcə xəbərdarlıq yerləşdirir. Android-də EventBus və ya Otto (köhnəlmiş). BroadcastChannel ilə SharedFlow — Kotlin dünyasında PubSub. Paylanmış sistemlərdə PubSub RabbitMQ, Kafka, Google PubSub vasitəsilə həyata keçirilir. Mobil inkişafda PubSub modul memarlığında faydalıdır, burada modullar bir-birindən asılı olmamalıdır.
Nə seçmək — UI yeniləmələri üçün (ViewModel → View) Observer istifadə edin (LiveData, StateFlow, @Published). Modullararası hadisələr üçün (avtorizasiya, hesabdan çıxış, mövzu dəyişikliyi) — PubSub (SharedFlow, NotificationCenter, EventBus). Observer bir ekran daxilində daha sadə və səmərəlidir, PubSub qlobal hadisələr üçün daha çevikdir, lakin gizli asılılıqlar səbəbindən sazlamada daha çətindir.
Tez-tez verilən suallar
StateFlow Kotlin Coroutines-dən platformadan asılı olmayan tipdir, LiveData Android Lifecycle-ə bağlıdır. StateFlow coroutines və operatorları dəstəkləyir, Android olmadan test edilir. LiveData abunəliyi LifecycleOwner vasitəsilə avtomatik idarə edir. Google Kotlin + Compose ilə yeni layihələr üçün StateFlow, Java uyğunluğu üçün LiveData tövsiyə edir.
Handler closure-da [weak self] istifadə edin və deinit-də removeObserver() çağırın. Observer-ə (NSObjectProtocol) istinad saxlayın və obyekt məhv edildikdə onu silin. Combine-də DisposeBag sərbəst buraxıldıqda avtomatik abunə ləğvi üçün AnyCancellable və store(in:) istifadə edin.
Bəli, SwiftUI @Published ilə ObservableObject və @StateObject/@ObservedObject-i dəstəkləyir — bu daxili Observer tətbiqidir. @Published avtomatik View-i dəyişikliklər barədə xəbərdar edir. Combine məcburi deyil: ObservableObject SwiftUI-yə daxil olan objectWillChange Publisher-dən istifadə edir. Combine axınların transformasiyası üçün operatorlar əlavə edir.
SharedFlow — birdəfəlik hadisələr (naviqasiya, tostlar, Snackbar) üçün, burada cari dəyər lazım deyil. StateFlow — UI vəziyyəti (verilənlər siyahısı, yükləmə vəziyyəti) üçün, burada cari snapshot lazımdır. SharedFlow value xassəsinə malik deyil və yeni abunəçilərə son dəyəri qaytarmır.
KVO — köhnəlmiş ObjC mexanizmi, @objc dynamic tələb edir və yalnız NSObject-dən miras alan siniflərlə işləyir. Combine — müasir Swift framework, tip təhlükəsiz, operatorlar və SwiftUI ilə inteqrasiya ilə. Combine KVO və NotificationCenter-i əvəz edir. Apple yeni layihələr üçün Combine, köhnə kodu dəstəkləmək üçün yalnız KVO tövsiyə edir.
Nəticələr
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