Observer — mga pangunahing konsepto ng pattern ng subscription sa mga pagbabago

May-akda: IT Sectr Nai-publish: 2026-02-17 Oras ng pagbabasa: 7 min

Observer — isang pattern ng pag-uugali kung saan ang isang bagay (tagapaglathala) ay nag-aabiso ng maraming tagasuskribi tungkol sa mga pagbabago sa estado nito. Sa pag-develop ng mobile, ang Observer ay nasa puso ng mga reaktibong mekanismo: ang UI ay nag-subscribe sa mga pagbabago ng data at awtomatikong nag-a-update. Ang pattern ay ipinatupad sa NotificationCenter sa iOS at LiveData/Flow sa Android. Higit pa — sa Refactoring Guru: Observer.

Mga Pangunahing Punto

  • Observer — pattern ng subscription: isang tagapaglathala, maraming tagasuskribi
  • NotificationCenter — built-in na implementasyon ng Observer sa iOS/macOS
  • Flow at LiveData — mga reaktibong implementasyon ng Observer sa Android
  • Push vs Pull — maaaring magpadala ng data ang tagapaglathala o mag-abiso tungkol sa mga kaganapan
  • Mga tagas ng memorya — dapat mag-unsubscribe ang mga tagasuskribi upang maiwasan ang mga tagas

Ano ang Observer: kakanyahan ng pattern ng tagamasid?

Observer (tagamasid) — isang GoF pattern ng pag-uugali na tumutukoy sa dependency na «isa-sa-marami» sa pagitan ng mga bagay. Kapag binago ng isang bagay (Subject o Observable) ang estado nito, lahat ng umaasang bagay (Observers) ay awtomatikong naaabiso at naa-update. Ang pattern ay nagpapatupad ng mahinang pagkabit: hindi alam ng tagapaglathala ang mga kongkretong klase ng mga tagasuskribi — alam lang na nagpapatupad sila ng interface ng Observer.

Istraktura ng Observer ay may kasamang interface ng Subject na may mga pamamaraang attach(), detach(), notify() at interface ng Observer na may pamamaraang update(). Ang ConcreteSubject ay nag-iimbak ng estado at listahan ng mga tagasuskribi. Ang ConcreteObserver ay nagpapatupad ng update() at tumutugon sa mga pagbabago. Sa pag-develop ng mobile, ang klasikong implementasyon ng GoF ay bihirang matagpuan — pinapalitan ito ng mga built-in na mekanismo: NotificationCenter, Combine, Flow, LiveData, na nagpapatupad ng parehong ideya gamit ang modernong API.

Modelong Push vs Pull — sa modelong Push, ang Subject ay nagpapadala ng data sa lahat ng tagasuskribi (NotificationCenter.post). Sa modelong Pull, ang Subject ay nag-aabiso lamang, at ang tagasuskribi mismo ang kumukuha ng data. Ang Android LiveData ay gumagamit ng Push (ang data ay ipinapasa sa observe()), sinusuportahan ng RxJava/Flow ang parehong modelo. Ang pagpili ay depende sa gawain: ang Push ay mas simple para sa mga update ng UI, ang Pull ay mas mahusay para sa malalaking volume ng data na maaaring hindi gustong matanggap ng tagasuskribi.

Observer sa iOS: NotificationCenter, Combine at KVO

NotificationCenter — ang built-in na mekanismo ng iOS/macOS para sa pagpapatupad ng Observer. Ang tagapaglathala ay nagpapadala ng Notification sa pamamagitan ng NotificationCenter.default.post(name:, object:, userInfo:). Ang tagasuskribi ay nagrerehistro sa pamamagitan ng addObserver(forName:, queue:, using:). Ang NotificationCenter ay sumusuporta sa mga pinangalanang abiso (Notification.Name) at maaaring magpasa ng anumang data sa userInfo. UIKeyboardWillShowNotification, UIApplicationDidEnterBackgroundNotification — mga halimbawa ng sistema.

swift
extension Notification.Name {
    static let userDidLogin = Notification.Name("userDidLogin")
}

// Tagapaglathala
NotificationCenter.default.post(
    name: .userDidLogin,
    object: nil,
    userInfo: ["userId": "123"]
)

// Tagasuskribi
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 }
            // Ang tagasuskribi ay tumutugon sa kaganapan
            self?.loadProfile(userId: userId)
        }
        observers.append(observer)
    }

    func stopObserving() {
        observers.forEach { NotificationCenter.default.removeObserver($0) }
        observers.removeAll()
    }
}

Combine framework — isang modernong reaktibong alternatibo sa NotificationCenter, available mula noong iOS 13. Publisher (NotificationCenter, URLSession.Timer) — tagapaglathala, Subscriber (sink, assign) — tagasuskribi. Nagdaragdag ang Combine ng mga operator (map, filter, combineLatest) para sa pagbabago ng daloy ng data. @Published — property wrapper na awtomatikong nag-aabiso sa mga tagasuskribi tungkol sa mga pagbabago. Sa MVVM na may SwiftUI, pinapalitan ng Combine ang NotificationCenter para sa pag-uugnay ng ViewModel at View.

KVO (Key-Value Observing) — isang lumang mekanismo ng ObjC/Swift para sa pagmamasid sa mga indibidwal na pag-aari ng mga bagay. @objc dynamic var name: String — naobserbahang pag-aari. observe(.name) — subscription. Ang KVO ay gumagana lamang sa mga klase na katugma sa @objc at pamana ng ObjC. Inirerekomenda ng Apple ang Combine at @Published sa halip na KVO sa mga bagong proyekto. Ang KVO ay nananatiling may kaugnayan para sa compatibility ng UIKit sa mga hybrid na proyekto.

Observer sa Android: LiveData, StateFlow at SharedFlow

LiveData — isang bahagi ng Android Architecture Components para sa pagpapatupad ng Observer. Isang klase ng Observable na nag-aabiso sa mga tagasuskribi tungkol sa mga pagbabago ng data. Isinasaalang-alang ng LiveData ang lifecycle: ang mga tagasuskribi (LifecycleOwner) ay awtomatikong nag-a-unsubscribe kapag nawasak. Ang LiveData ay modelong Push: ang data ay ipinapasa sa observe(). Ang LiveData ay ang pangunahing bloke ng gusali ng MVVM sa Android bago ang pagpapakilala ng Jetpack Compose.

kotlin
// ViewModel — tagapaglathala
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 — tagasuskribi
class UserFragment : Fragment() {
    private val viewModel: UserViewModel by viewModels()

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        viewModel.user.observe(viewLifecycleOwner) { user ->
            // Ang tagasuskribi ay tumutugon sa mga pagbabago
            userName.text = user?.name
            userEmail.text = user?.email
        }
    }
}

StateFlow at SharedFlow — mga reaktibong uri mula sa Kotlin Coroutines na pumalit sa LiveData sa Jetpack Compose. StateFlow — observable state holder na may nakapirming kasalukuyang halaga. SharedFlow — nako-configure na hot flow na walang estado, angkop para sa isang beses na mga kaganapan (nabigasyon, toast). Ang parehong uri ay malapit na isinama sa Compose: collectAsState(), collectAsEffect(). Ang StateFlow ay sapilitan sa mga modernong proyekto ng Android na may Compose.

LiveData vs StateFlow — ang LiveData ay nakatali sa Android Lifecycle, ang StateFlow ay independiyente sa platform. Sinusuportahan ng StateFlow ang coroutines, operator (map, filter) at sinusuri nang walang mga dependency sa Android. Ang LiveData ay mas simple para sa compatibility ng Java. Inirerekomenda ng Google ang StateFlow para sa mga bagong proyekto na may Kotlin + Compose, LiveData — para sa suporta ng mga lumang proyekto o Java code.

Pamamahala ng mga subscription at mga tagas ng memorya

Mga tagas ng memorya (memory leaks) — ang pangunahing problema ng Observer nang walang tamang pamamahala ng subscription. Kung ang isang tagasuskribi (Activity, Fragment, UIViewController) ay nawasak ngunit hindi nag-unsubscribe, ang tagapaglathala ay patuloy na humahawak ng sanggunian dito, at hindi mapapalaya ng garbage collector ang memorya. Sa Android, ang LifecycleOwner (Activity/Fragment) ay dapat tumawag ng removeObserver() o gumamit ng observe(viewLifecycleOwner). Sa iOS — removeObserver sa deinit o disposeBag sa Combine.

PlatformMekanismo ng ObserverAwtomatikong pag-unsubscribeManual na pag-unsubscribe
iOSNotificationCenterHindiremoveObserver() sa deinit
iOSCombine (sink)Hindistore(in: &bag) — DisposeBag
iOSKVOHindiremoveObserver() sa deinit
AndroidLiveDataOo (LifecycleOwner)removeObserver() opsyonal
AndroidStateFlowSa pamamagitan ng viewModelScopecancel() Job sa pag-unsubscribe
AndroidRxJavaHindidispose() sa CompositeDisposable

Mahinang sanggunian (weak reference) sa mga tagasuskribi — sa bloke ng subscription gamitin ang [weak self] sa Swift at sumangguni sa lifecycle scope sa Kotlin. Awtomatikong pinamamahalaan ng LiveData ang subscription sa pamamagitan ng LifecycleOwner — ang subscription ay aktibo lamang kapag ang Lifecycle ay nasa estado ng STARTED o RESUMED. Ang StateFlow sa Compose ay gumagamit ng collectAsState() na isinasaalang-alang ang lifecycle. Ang NotificationCenter sa iOS ay nangangailangan ng tahasang [weak self], dahil ang closure ay malakas na sumasangguni sa self.

Observer vs Publisher-Subscriber: ano ang pagkakaiba

Observer (GoF) at Publisher-Subscriber (PubSub) — magkatulad ngunit magkaibang mga pattern. Sa Observer, direktang inaabiso ng tagapaglathala ang mga tagasuskribi sa pamamagitan ng pagtawag sa kanilang mga pamamaraan. Alam ng tagapaglathala ang mga tagasuskribi (nag-iimbak ng listahan). Sa PubSub, hindi alam ng tagapaglathala at tagasuskribi ang isa’t isa — may tagapamagitan (Event Bus, Message Queue, NotificationCenter) sa pagitan nila. Ang tagapaglathala ay nagpapadala ng mensahe sa isang channel, ang tagasuskribi ay nakikinig sa channel. Ang PubSub ay nagbibigay ng mas mahinang pagkabit.

Mga halimbawa ng PubSub sa pag-develop ng mobile — ang NotificationCenter sa iOS ay maaaring ituring na PubSub: hindi kilala ng tagapaglathala ang mga tagasuskribi — nagpo-post lamang ito ng abiso. EventBus o Otto sa Android (luma na). SharedFlow na may BroadcastChannel — PubSub sa mundo ng Kotlin. Sa mga distributed system, ang PubSub ay ipinatutupad sa pamamagitan ng RabbitMQ, Kafka, Google PubSub. Para sa pag-develop ng mobile, ang PubSub ay kapaki-pakinabang sa modular na arkitektura, kung saan ang mga module ay hindi dapat umasa sa isa’t isa.

Ano ang pipiliin — para sa mga update ng UI (ViewModel → View) gamitin ang Observer (LiveData, StateFlow, @Published). Para sa mga inter-module na kaganapan (awtorisasyon, pag-logout, pagbabago ng tema) — PubSub (SharedFlow, NotificationCenter, EventBus). Ang Observer ay mas simple at mahusay sa loob ng isang screen, ang PubSub ay mas nababaluktot para sa mga pandaigdigang kaganapan ngunit mas mahirap i-debug dahil sa mga implicit na dependency.

Mga Madalas Itanong

Paano naiiba ang StateFlow sa LiveData?

Ang StateFlow ay isang uri na independiyente sa platform mula sa Kotlin Coroutines, ang LiveData ay nakatali sa Android Lifecycle. Sinusuportahan ng StateFlow ang coroutines at operator, sinusuri nang walang Android. Awtomatikong pinamamahalaan ng LiveData ang subscription sa pamamagitan ng LifecycleOwner. Inirerekomenda ng Google ang StateFlow para sa mga bagong proyekto na may Kotlin + Compose, LiveData — para sa compatibility ng Java.

Paano maiiwasan ang mga tagas ng memorya sa NotificationCenter?

Gamitin ang [weak self] sa closure ng handler at tawagan ang removeObserver() sa deinit. Mag-imbak ng sanggunian sa observer (NSObjectProtocol) at tanggalin ito sa pagkasira ng bagay. Sa Combine, gamitin ang AnyCancellable at store(in:) para sa awtomatikong pag-unsubscribe kapag pinalaya ang DisposeBag.

Maaari bang gamitin ang Observer sa SwiftUI nang walang Combine?

Oo, sinusuportahan ng SwiftUI ang ObservableObject na may @Published at @StateObject/@ObservedObject — ito ay isang built-in na implementasyon ng Observer. Awtomatikong inaabiso ng @Published ang View tungkol sa mga pagbabago. Hindi kinakailangan ang Combine: ang ObservableObject ay gumagamit ng objectWillChange Publisher na naka-embed sa SwiftUI. Nagdaragdag ang Combine ng mga operator para sa pagbabago ng daloy.

Kailan gagamitin ang SharedFlow sa halip na StateFlow?

SharedFlow — para sa isang beses na mga kaganapan (nabigasyon, toast, Snackbar) kung saan hindi kailangan ang kasalukuyang halaga. StateFlow — para sa estado ng UI (listahan ng data, progreso ng pag-load) kung saan kailangan ang kasalukuyang snapshot. Ang SharedFlow ay walang value property at hindi ibinabalik ang huling halaga sa mga bagong tagasuskribi.

Ano ang pagkakaiba sa pagitan ng KVO at Combine sa iOS?

Ang KVO ay isang lumang mekanismo ng ObjC, nangangailangan ng @objc dynamic at gumagana lamang sa mga klase na nagmamana ng NSObject. Ang Combine ay isang modernong Swift framework, type-safe, na may mga operator at integrasyon sa SwiftUI. Pinapalitan ng Combine ang KVO at NotificationCenter. Inirerekomenda ng Apple ang Combine para sa mga bagong proyekto, KVO — para lamang sa suporta ng lumang code.

Buod

  • Observer — pattern ng pag-uugali para sa pag-abiso ng mga tagasuskribi tungkol sa mga pagbabago
  • iOS NotificationCenter — implementasyon ng PubSub na may mga pinangalanang abiso
  • iOS Combine — reaktibong framework na may Publisher at Subscriber
  • Android LiveData — lifecycle-aware Observer mula sa Android Architecture Components
  • Android StateFlow — reaktibong state holder para sa Compose at coroutine
  • Pamamahala ng memorya — sapilitang pag-unsubscribe upang maiwasan ang mga tagas
  • Observer vs PubSub — direktang subscription vs tagapamagitan para sa mahinang pagkabit

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