EventBus: nedir, çalışma prensibi ve Android olay veriyolu

Yazar: IT Sectr Yayınlanma: 2026-03-18 Okuma süresi: 10 dk

EventBus, bir olay veriyolu aracılığıyla Publisher-Subscriber modelini uygulayan ve bileşenler arasında doğrudan bağımlılık olmadan veri alışverişine izin veren bir Android kütüphanesidir. GreenRobot tarafından geliştirilen kütüphane, Activity, Fragment, Service ve Background Thread arasındaki iletişimi basitleştirir. GitHub verilerine (2025) göre EventBus, 25 binden fazla yıldıza sahiptir ve binlerce Android uygulamasında kullanılmaktadır. Ana işlemler subscribe (bir olaya abone olma), post (bir olay gönderme) ve sticky event (yeni aboneler için ertelenmiş olay)dır.

Önemli Noktalar

  • EventBus, Android'de gevşek bağlı iletişim için bir olay veriyolu kütüphanesidir.
  • @Subscribe, bir yöntemi belirli bir olay türünün işleyicisi olarak işaretleyen bir ek açıklamadır.
  • EventBus.getDefault().post(), abone olan tüm işleyicilere bir olay gönderir.
  • Sticky event, yeni abonelere teslim etmek için son olayı saklar.
  • ThreadMode, işleyici yürütme iş parçacığını belirler: MAIN, POSTING, BACKGROUND, ASYNC.

EventBus Nedir?

EventBus, Publisher-Subscriber modelini uygulayan Android için bir olay veriyolu kütüphanesidir. Uygulama bileşenleri (Activity, Fragment, Service, ViewModel) arasında açık bağımlılıklar oluşturmadan olayların iletilmesine izin verir. Standart Android mekanizmalarının (Intent, BroadcastReceiver) aksine, EventBus işlem içinde çalışır ve IPC kullanmaz. Kütüphane performans için optimize edilmiştir ve Subscriber Index doğru yapılandırıldığında yansıma kullanmaz.

GreenRobot EventBus: Mimari

EventBus mimarisi üç temel unsurdan oluşur: Event (veri içeren POJO sınıfı), Subscriber (@Subscribe ile işaretlenmiş yöntemlere sahip nesne) ve EventBus (merkezi dağıtıcı). Abone, EventBus.getDefault().register(this) aracılığıyla kaydolur ve unregister(this) aracılığıyla kaydı iptal eder. Olaylar türlendirilmiştir: işleyiciler belirli bir olay sınıfına abone olur ve yalnızca bu sınıfın veya alt sınıflarının bir olayı yayınlandığında çağrılır.

kotlin
// POJO olayı
data class MessageEvent(
    val message: String,
    val timestamp: Long = System.currentTimeMillis()
)

// Activity'de abone
class MainActivity : AppCompatActivity() {

    override fun onStart() {
        super.onStart()
        EventBus.getDefault().register(this)
    }

    override fun onStop() {
        EventBus.getDefault().unregister(this)
        super.onStop()
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    fun onMessageEvent(event: MessageEvent) {
        textView.text = event.message
    }
}

// Başka bir bileşenden olay gönderme
EventBus.getDefault().post(MessageEvent("Hello from Service"))

Performans için Subscriber Index

Varsayılan olarak, EventBus register() sırasında @Subscribe yöntemlerini bulmak için yansıma kullanır. Subscriber Index, bir ek açıklama işlemcisi aracılığıyla derleme zamanında bir işleyici dizini oluşturur. Bu, yansıma yükünü ortadan kaldırır ve kaydı hızlandırır. Etkinleştirmek için build.gradle'a eventbus-annotation-processor ekleyin. EventBus, classpath'te mevcutsa dizini otomatik olarak kullanır. Dizin olmadan kütüphane yine de çalışır, ancak hafif bir performans düşüşü olur.

EventBus Android'de Nasıl Çalışır?

EventBus.getDefault().post(event) çağrıldığında, kütüphane olay türünü belirler, bu türü kabul eden @Subscribe yöntemlerine sahip tüm kayıtlı aboneleri bulur ve bunları belirtilen ThreadMode'a göre çağırır. Abone arama, kayıt sırasında oluşturulan Class → CopyOnWriteArrayList haritası kullanılarak gerçekleştirilir. Bir olayın abonesi yoksa, post hata olmadan tamamlanır — bu güvenli başarısızlık davranışıdır.

Kayıt Yaşam Döngüsü

Bir abone onStart() içinde kaydolmalı ve onStop() içinde kaydı iptal etmelidir. onCreate() içinde kaydolup onDestroy() içinde iptal ederseniz, finish() nedeniyle onDestroy'u çağırmadan yok edilen bir Activity abone listesinde kalabilir. Abone sızıntısı, EventBus'ın ana sorunlarından biridir: abone listesinde kalan bir Activity, kaydı iptal edene kadar GC tarafından serbest bırakılmaz. Her zaman register/unregister'ı doğru yaşam döngüsü yöntemlerinde eşleştirin.

İşleyici Önceliği

@Subscribe ek açıklaması bir priority parametresini (tamsayı, varsayılan 0) destekler. Daha yüksek önceliğe sahip işleyiciler önce çağrılır. cancelEventDelivery(), kalan abonelere olay teslimatını kesmeye izin verir. Bu, alt akış aboneleri tarafından olay işlemeyi iptal edebilen öncelikli işleyiciler (günlükleme, kimlik doğrulama) için kullanışlıdır. Bu işlev yalnızca olay yayınlama iş parçacığında kullanılabilir.

kotlin
// Öncelikli karmaşık örnek
data class NavigationEvent(val screen: String, val data: Bundle)

class NavigationInterceptor {
    @Subscribe(priority = 10, threadMode = ThreadMode.POSTING)
    fun onNavigationEvent(event: NavigationEvent) {
        if (event.screen == "restricted" && !isAuthorized) {
            EventBus.getDefault().cancelEventDelivery(event)
        }
    }
}

class AnalyticsLogger {
    @Subscribe(priority = 5)
    fun logNavigation(event: NavigationEvent) {
        analytics.logScreen(event.screen)
    }
}

// Olay gönderme
EventBus.getDefault().post(NavigationEvent("profile", bundle))

EventBus vs LocalBroadcastManager vs LiveData

Android, işlem içi iletişim için çeşitli mekanizmalar sunar: EventBus, LocalBroadcastManager (kullanımdan kaldırıldı) ve LiveData/Flow. Her birinin avantajları ve dezavantajları vardır. Seçim, mimari yaklaşıma ve performans gereksinimlerine bağlıdır. Google'ın modern önerileri, Lifecycle entegrasyonu ve sızıntıların olmaması nedeniyle LiveData ve Flow'a yönelmektedir.

ÖzellikEventBusLocalBroadcastManagerLiveData / Flow
TürlemeOlay sınıfıylaIntent filtresiyle (String)Jenerik türle
Lifecycle-awareHayır (manuel iptal)Hayır (manuel iptal)Evet (otomatik)
StickyEvet (postSticky)HayırEvet (LiveData her zaman sticky)
ThreadModeMAIN, POSTING, BACKGROUND, ASYNCSadece mainobserve/observeOn ile
PerformansYüksek (Subscriber Index)Orta (IPC sarmalayıcısı)Yüksek (gözlem)

EventBus Ne Zaman Tercih Edilir

EventBus, önemli miktarda eski kod içeren projelerde ve LiveData/Flow'un mevcut olmadığı (yalnızca Java projeleri) durumlarda kullanışlıdır. EventBus'ın sticky events özelliği, LocalBroadcastManager'da bulunmayan esneklik sağlar. EventBus ayrıca ViewModel olmadan Service'ten Activity'ye olay göndermek için daha kolaydır — özellikle bir arka plan görevinin ilerlemesini bildirmeniz gerektiğinde. Kütüphane minimum boyuta (yaklaşık 50 KB) sahiptir ve bağımlılık eklemez.

LiveData/Flow Ne Zaman Tercih Edilir

LiveData ve Flow, Android Jetpack'in bir parçasıdır ve Lifecycle ile entegredir. Bir bileşen yok edildiğinde otomatik olarak abonelikten çıkarlar ve bellek sızıntılarını ortadan kaldırırlar. Flow, eş yordamları ve karmaşık dönüşüm operatörlerini destekler. Google, UI katmanı için LiveData'yı ve depolar için Flow'u önerir. EventBus, gezinme ve iş mantığının MVVM'ye uymadığı modüller arası olaylar için kullanışlı olmaya devam eder.

Subscribe ve Post: Temel İşlemler

Subscribe, @Subscribe ek açıklaması aracılığıyla bir olay işleyicisinin kaydedilmesidir. Yöntem public, void olmalı ve tam olarak bir parametre — olay türü — kabul etmelidir. Post, EventBus.getDefault().post(event) aracılığıyla abone olan tüm işleyicilere bir olay göndermektir. Post yöntemi bir sonuç döndürmez ve kaç işleyicinin çağrıldığını belirtmez. Yanıt gerektiren olaylar için, bir sonuç alanına sahip ayrı bir Event sınıfı kullanın.

Özel Olaylar Oluşturma

Bir olay, herhangi bir Java/Kotlin sınıfıdır. Değişmez olaylar için data class ve değişebilir alanlara sahip olaylar için normal bir sınıf kullanılması önerilir. Olay adlandırması eylemi yansıtmalıdır: UserLoggedInEvent, DataLoadedEvent, NetworkErrorEvent. String türü alanı olan tek bir genel Event sınıfından kaçının — bu, türlemenin avantajlarını ortadan kaldırır. Bir olay hiyerarşisi (üst Event), ilgili olay grubuna abone olmaya izin verir.

kotlin
// Olay hiyerarşisi
open class UserEvent
data class UserLoggedIn(val userId: String) : UserEvent()
data class UserLoggedOut(val reason: String) : UserEvent()

// Temel sınıfa abone olma
class SessionManager {
    @Subscribe(threadMode = ThreadMode.MAIN)
    fun onUserEvent(event: UserEvent) {
        when (event) {
            is UserLoggedIn -> startSession(event.userId)
            is UserLoggedOut -> endSession(event.reason)
        }
    }
}

// Gönderme
EventBus.getDefault().post(UserLoggedIn("user_123"))

Kayıt ve Kayıt İptali

EventBus.getDefault().register(this) çağırmak, abone sınıfını yansıma veya Subscriber Index aracılığıyla tarar ve bulunan @Subscribe yöntemlerini olay haritasında saklar. Unregister, aboneyi haritadan kaldırır. Kayıt iptal etmeden yeniden kaydolmak bir hatadır (MultipleSubscriberException fırlatır). Fragment için onStart() içinde kaydolun ve onStop() içinde iptal edin. Service için onCreate() ve onDestroy() içinde. ViewModel için önerilmez — LiveData kullanın.

Sticky Events ve ThreadMode

Sticky event, gönderildikten sonra EventBus'ta kalan bir olaydır. postSticky()'den sonra kaydolan yeni aboneler, ilgili türün son sticky event'ini hemen alır. Bu, başlangıç durumunu iletmek için kullanışlıdır: bir ekran açıldığında, kaydından önce gönderilen en son verileri alır. Bir sticky event'i EventBus.getDefault().removeStickyEvent(Class) aracılığıyla kaldırabilirsiniz.

ThreadMode: Dört Yürütme Modu

ThreadMode, işleyicinin hangi iş parçacığında yürütüleceğini belirler. POSTING (varsayılan) — işleyici, post'un çağrıldığı aynı iş parçacığında çalışır. MAIN — işleyici, Handler aracılığıyla ana iş parçacığında çalışır. BACKGROUND — işleyici bir arka plan iş parçacığında çalışır; post ana iş parçacığında çağrıldıysa, EventBus işleyiciyi bir arka plan iş parçacığı kuyruğuna koyar. ASYNC — her işleyici, bir iş parçacığı havuzundan ayrı bir arka plan iş parçacığında çalışır. UI güncellemeleri için MAIN kullanın.

kotlin
// Sticky Event
data class LocationEvent(val lat: Double, val lng: Double)

// LocationService'ten sticky olay gönderme
EventBus.getDefault().postSticky(LocationEvent(55.7558, 37.6173))

// Abone, kayıttan hemen sonra son konumu alır
class MapFragment : Fragment() {
    override fun onStart() {
        super.onStart()
        EventBus.getDefault().register(this)
        // postSticky çağrıldıysa hemen LocationEvent alır
    }

    override fun onStop() {
        EventBus.getDefault().unregister(this)
        super.onStop()
    }

    @Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
    fun onLocationEvent(event: LocationEvent) {
        moveMapTo(event.lat, event.lng)
    }
}

// Sticky olayı kaldırma
EventBus.getDefault().removeStickyEvent(LocationEvent::class.java)

ThreadMode.BACKGROUND vs ASYNC

BACKGROUND, tüm işleyiciler için tek bir arka plan iş parçacığı kullanır — sırayla yürütülürler. ASYNC, her işleyici için havuzdan yeni bir iş parçacığı oluşturur — paralel olarak yürütülürler. BACKGROUND, paylaşılan bir veritabanıyla G/Ç işlemleri için uygundur. ASYNC, bağımsız uzun süreli işlemler (ağ istekleri) içindir. Her iki mod da paylaşılan kaynaklara iş parçacığı güvenli erişim gerektirir. İş parçacığı sayısını aklınızda bulundurun: ASYNC havuzu sınırsızdır.

Yaygın EventBus Hataları ve Performans

EventBus'ı kullanırken geliştiriciler sıklıkla bellek sızıntılarına, beklenmeyen çağrılara ve performans düşüşüne yol açan hatalar yapar. En kritik olanlar: Activity'de kayıt iptalini unutmak, onCreate'te kaydolmak (onStart/onStop yerine), Object'e (tüm olaylar) abone olmak, sonsuz döngüde olay göndermek. Android Profiler ile profil oluşturma, sorunları belirlemeye yardımcı olur.

EventBus Aracılığıyla Bellek Sızıntıları

En yaygın hata, onDestroy() içinde kaydı iptal etmeden onCreate() içinde bir Activity kaydetmektir. Sonuç: EventBus, Activity'ye bir referans tutar, GC onu serbest bırakamaz. Ekran döndürüldüğünde, önceki Activity bellekte kalırken yeni bir Activity oluşturulur. Çözüm: her zaman onStart/onStop içinde register/unregister'ı eşleştirin. Fragment için aynı modeli kullanın. Bir Activity, finish'ten sonra EventBus tarafından tutuluyorsa, Memory Profiler ile kontrol edin.

Performans: Subscriber Index

Subscriber Index olmadan, EventBus her register()'da @Subscribe yöntemlerini bulmak için yansıma kullanır. Android 6-7 cihazlarında yansıma yavaştır ve 50 ms'ye kadar gecikmelere neden olur. Subscriber Index, yansımayı tamamen ortadan kaldırır: yöntemler, bir ek açıklama işlemcisi aracılığıyla derleme zamanında indekslenir. 20'den fazla abonesi olan projeler için dizin zorunludur. build.gradle'da kapt veya annotationProcessor'ın yapılandırıldığından emin olun.

groovy
// build.gradle (app) — Subscriber Index ekleme
dependencies {
    implementation 'org.greenrobot:eventbus:3.3.1'
    annotationProcessor 'org.greenrobot:eventbus-annotation-processor:3.3.1'
}

// Kotlin için kapt kullanın
plugins {
    id 'kotlin-kapt'
}

dependencies {
    implementation 'org.greenrobot:eventbus:3.3.1'
    kapt 'org.greenrobot:eventbus-annotation-processor:3.3.1'
}

// Dizin yapılandırması (defaultConfig içinde)
kapt {
    arguments {
        arg('eventBusIndex', 'com.app.EventBusIndex')
    }
}

Modern Android'de EventBus Alternatifleri

Kotlin ve Jetpack Compose kullanan modern projeler, kotlinx.coroutines kütüphanesinden SharedFlow ve Channel'ı tercih eder. SharedFlow, tekrar oynatma (sticky), arabelleğe alma ve geri basıncı destekler. Channel, tek seferlik olayları (toast, gezinme) işler. Her iki çözüm de repeatOnLifecycle aracılığıyla Lifecycle ile entegredir ve manuel abonelik iptali gerektirmez. Yeni projeler için EventBus yerine SharedFlow önerilir. Mevcut projeler için yeniden düzenleme sırasında geçiş yapmak haklıdır.

Sıkça Sorulan Sorular

EventBus ve LiveData arasındaki fark nedir?

EventBus, herhangi bir bileşen (Activity, Fragment, Service) arasında veri alışverişi için bir olay veriyoludur. LiveData, bir UI bileşeni tarafından gözlemlenen veriler için lifecycle-aware bir sarmalayıcıdır. LiveData, Lifecycle aracılığıyla aboneliği otomatik olarak yönetir. EventBus manuel register/unregister gerektirir. LiveData UI katmanı için, EventBus ise LiveData'nın uygun olmadığı modüller arası iletişim için önerilir.

Sticky event nedir?

Sticky event, gönderildikten sonra EventBus'ta kalan bir olaydır. postSticky()'den sonra kaydolan yeni aboneler, son sticky event'i hemen alır. Başlangıç durumu için kullanılır: bir ekran açıldığında, yeni bir istek olmadan en son verileri alır. removeStickyEvent() ile veya aynı türde yeni bir sticky event gönderildiğinde kaldırılır.

EventBus iş parçacığı güvenli midir?

Evet, EventBus iş parçacığı güvenlidir. post() herhangi bir iş parçacığından çağrılabilir. Abonelere olay teslimatı dahili olarak senkronize edilir. ThreadMode, işleyici yürütme iş parçacığını belirler: MAIN (Handler aracılığıyla ana iş parçacığı), POSTING (çağıran iş parçacığı), BACKGROUND (arka plan görev kuyruğu), ASYNC (ayrı iş parçacığı). UI güncellemeleri için MAIN, ağır işlemler için ASYNC kullanın.

EventBus nasıl hata ayıklanır?

EventBus.builder().logNoSubscriberMessages(true).sendNoSubscriberEvent(true).install() ile günlük kaydını etkinleştirin. İşleyicisi olmayan olayları izlemek için NoSubscriberEvent'e abone olun. Global istisna işleme için SubscriberExceptionEvent kullanın. Android Profiler sızıntıları bulmaya yardımcı olur. Karmaşık senaryolar için bir test yazın: EventBus.getDefault().register(mock) + post(event) + verify(mock).

EventBus Kotlin Multiplatform'da kullanılabilir mi?

Hayır, EventBus (GreenRobot) Android SDK ve JVM'ye bağlıdır. Kotlin Multiplatform için Kotlin Multiplatform SharedFlow veya KMMBus — paylaşılan kodu destekleyen kütüphaneleri kullanın. EventBus, bir KMM projesinin Android tarafında çalışır ancak commonMain'de kullanılamaz. Platformlar arası olaylar için platformun yerel mekanizmalarını veya expect/actual aracılığıyla soyutlamayı tercih edin.

Özet

  • EventBus, POJO sınıfları aracılığıyla türleme ile bir olay veriyolu uygulayan Android için Publisher-Subscriber kütüphanesidir.
  • threadMode, sticky, priority parametrelerine sahip @Subscribe ek açıklaması, olay işleyici davranışını tanımlar.
  • post() tüm abonelere eşzamanlı olarak bir olay gönderir; postSticky() yeni aboneler için olayı saklar.
  • ThreadMode yürütme iş parçacığını kontrol eder: POSTING (çağıran iş parçacığı), MAIN (UI), BACKGROUND (kuyruk), ASYNC (havuz).
  • Ek açıklama işlemcisi aracılığıyla Subscriber Index yansımayı ortadan kaldırır ve kaydı hızlandırır.
  • Bellek sızıntıları, Activity veya Fragment'in onStart/onStop'unda eşleştirilmiş register/unregister ile önlenir.
  • Yeni projeler için kotlinx.coroutines'den SharedFlow/Channel tercih edilir — lifecycle-aware ve iş parçacığı güvenlidirler.

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.

Projeyi tartış

Ayrıca okuyun