EventBus Android uchun kutubxona bo'lib, Publisher-Subscriber naqshini hodisalar shinasi orqali amalga oshiradi va komponentlar o'rtasida to'g'ridan-to'g'ri bog'liqliksiz ma'lumot almashish imkonini beradi. GreenRobot tomonidan ishlab chiqilgan kutubxona Activity, Fragment, Service va Background Thread o'rtasidagi aloqani soddalashtiradi. GitHub ma'lumotlariga ko'ra (2025), EventBus 25 mingdan ortiq yulduzga ega va minglab Android ilovalarida qo'llaniladi. Asosiy operatsiyalar — subscribe (hodisaga obuna bo'lish), post (hodisani yuborish) va sticky event (yangi obunachilar uchun kechiktirilgan hodisa).
Asosiy fikrlar
EventBus Android uchun hodisalar shinasi kutubxonasi bo'lib, Publisher-Subscriber (nashr qiluvchi-obunachi) naqshini amalga oshiradi. Ilova komponentlari (Activity, Fragment, Service, ViewModel) o'rtasida ular o'rtasida aniq bog'liqliklarni yaratmasdan hodisalarni uzatish imkonini beradi. Standart Android mexanizmlaridan (Intent, BroadcastReceiver) farqli o'laroq, EventBus jarayon ichida ishlaydi va IPC dan foydalanmaydi. Kutubxona unumdorlik uchun optimallashtirilgan va Subscriber Index to'g'ri sozlanganida refleksiyadan foydalanmaydi.
EventBus arxitekturasi uchta asosiy elementdan iborat: Event (ma'lumotlar bilan POJO sinfi), Subscriber (@Subscribe bilan belgilangan metodlari bo'lgan obyekt) va EventBus (markaziy dispetcher). Obunachi EventBus.getDefault().register(this) orqali ro'yxatdan o'tadi, chiqish — unregister(this) orqali. Hodisalar tiplashtirilgan: ishlovchilar ma'lum bir hodisa sinfiga obuna bo'ladi va faqat shu sinf yoki uning pastki sinflarining hodisasi post qilinganida chaqiriladi.
// POJO hodisasi
data class MessageEvent(
val message: String,
val timestamp: Long = System.currentTimeMillis()
)
// Activity dagi obunachi
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
}
}
// Hodisani boshqa komponentdan yuborish
EventBus.getDefault().post(MessageEvent("Hello from Service"))
Odatiy bo'lib, EventBus register() vaqtida @Subscribe metodlarini topish uchun refleksiyadan foydalanadi. Subscriber Index kompilyatsiya bosqichida annotatsiya protsessori orqali ishlovchilar indeksini yaratadi. Bu refleksiya yukini bartaraf qiladi va ro'yxatdan o'tishni tezlashtiradi. Faollashtirish uchun build.gradle ga eventbus-annotation-processor qo'shing. EventBus classpath da mavjud bo'lsa, indeksni avtomatik ishlatadi. Indekssiz kutubxona hali ham ishlaydi, lekin unumdorlik biroz past bo'ladi.
EventBus.getDefault().post(event) chaqirilganda, kutubxona hodisa turini aniqlaydi, ushbu turni qabul qiluvchi @Subscribe metodlari bo'lgan barcha ro'yxatdan o'tgan obunachilarni topadi va ularni belgilangan ThreadMode ga muvofiq chaqiradi. Obunachilarni qidirish ro'yxatdan o'tish vaqtida qurilgan Class → CopyOnWriteArrayList
Obunachi onStart() da ro'yxatdan o'tishi va onStop() da chiqishi kerak. Agar onCreate() da ro'yxatdan o'tib, onDestroy() da chiqsa, onDestroy chaqirilmasdan yo'q qilingan Activity (finish() sababli) obunachilar ro'yxatida qolishi mumkin. Obunachi sizib chiqishi — EventBus ning asosiy muammolaridan biri: obunachilar ro'yxatida qolgan Activity chiqmaguncha GC tomonidan yig'ilmaydi. Har doim register/unregister ni to'g'ri lifecycle metodlarida juftlang.
@Subscribe annotatsiyasi priority parametrini qo'llab-quvvatlaydi (butun son, odatiy 0). Yuqori prioritetli ishlovchilar oldinroq chaqiriladi. cancelEventDelivery() hodisaning qolgan obunachilarga yetkazilishini to'xtatish imkonini beradi. Bu prioritet ishlovchilar (loglash, autentifikatsiya) uchun foydali bo'lib, ular pastdagi obunachilar tomonidan hodisani qayta ishlashni bekor qilishi mumkin. Funksiya faqat hodisa yuborish oqimida mavjud.
// Prioritetli murakkab misol
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)
}
}
// Hodisani yuborish
EventBus.getDefault().post(NavigationEvent("profile", bundle))
Android ichki jarayon aloqasi uchun bir nechta mexanizmlarni taklif qiladi: EventBus, LocalBroadcastManager (eskirgan) va LiveData/Flow. Har birining afzalliklari va kamchiliklari bor. Tanlov arxitektura yondashuvi va unumdorlik talablariga bog'liq. Google ning zamonaviy tavsiyalari Lifecycle bilan integratsiya va sizib chiqishlarning yo'qligi sababli LiveData va Flow ga moyil.
| Xususiyat | EventBus | LocalBroadcastManager | LiveData / Flow |
|---|---|---|---|
| Tiplashtirish | Hodisa sinfi orqali | Intent filter (String) orqali | Generic tip orqali |
| Lifecycle-aware | Yo'q (qo'lda chiqish) | Yo'q (qo'lda chiqish) | Ha (avtomatik) |
| Sticky | Ha (postSticky) | Yo'q | Ha (LiveData — har doim sticky) |
| ThreadMode | MAIN, POSTING, BACKGROUND, ASYNC | Faqat main | observe/observeOn orqali |
| Unumdorlik | Yuqori (Subscriber Index) | O'rtacha (IPC o'rami) | Yuqori (kuzatish) |
EventBus katta merosga ega loyihalarda (legacy code) va LiveData/Flow mavjud bo'lmagan joylarda (Java-only loyihalari) foydali. EventBus ning Sticky events i LocalBroadcastManager da yo'q egiluvchanlikni beradi. EventBus shuningdek ViewModelsiz Service dan Activity ga hodisalarni yuborish uchun soddaroq — ayniqsa fon vazifasining borishi haqida xabardor qilish kerak bo'lganda. Kutubxona minimal o'lchamga ega (taxminan 50 KB) va bog'liqlik qo'shmaydi.
LiveData va Flow Android Jetpack ning bir qismi va Lifecycle bilan integratsiyalangan. Komponent yo'q qilinganda avtomatik ravishda obunadan chiqadi, xotira sizib chiqishlarini bartaraf qiladi. Flow korutinlarni va murakkab transformatsiya operatorlarini qo'llab-quvvatlaydi. Google LiveData ni UI qatlami uchun, Flow ni esa repozitoriyalar uchun tavsiya qiladi. EventBus navigatsiya va biznes mantig'i MVVM ga mos kelmaydigan modullararo hodisalar uchun qoladi.
Subscribe — @Subscribe annotatsiyasi orqali hodisa ishlovchisini ro'yxatdan o'tkazish. Metod public, void bo'lishi va aniq bir parametrni — hodisa turini qabul qilishi kerak. Post — EventBus.getDefault().post(event) orqali hodisani barcha obuna bo'lgan ishlovchilarga yuborish. Post metodi natija qaytarmaydi va nechta ishlovchi chaqirilgani haqida xabar bermaydi. Javob talab qiladigan hodisalar uchun natija maydoni bo'lgan alohida Event sinfidan foydalaning.
Hodisa — har qanday Java/Kotlin sinfi. O'zgarmas hodisalar uchun data class, mutable maydonlari bo'lgan hodisalar uchun oddiy sinfdan foydalanish tavsiya etiladi. Hodisalarni nomlash harakatni aks ettirishi kerak: UserLoggedInEvent, DataLoadedEvent, NetworkErrorEvent. String type maydoni bo'lgan umumiy Event sinfidan saqlaning — bu tiplashtirishning afzalliklarini yo'qotadi. Hodisalar iyerarxiyasi (ota Event) qarindosh hodisalar guruhiga obuna bo'lish imkonini beradi.
// Hodisalar iyerarxiyasi
open class UserEvent
data class UserLoggedIn(val userId: String) : UserEvent()
data class UserLoggedOut(val reason: String) : UserEvent()
// Bazaviy sinfga obuna bo'lish
class SessionManager {
@Subscribe(threadMode = ThreadMode.MAIN)
fun onUserEvent(event: UserEvent) {
when (event) {
is UserLoggedIn -> startSession(event.userId)
is UserLoggedOut -> endSession(event.reason)
}
}
}
// Yuborish
EventBus.getDefault().post(UserLoggedIn("user_123"))
EventBus.getDefault().register(this) chaqiruvi obunachi sinfini refleksiya yoki Subscriber Index orqali skanerlash va topilgan @Subscribe metodlarini hodisalar xaritasida saqlaydi. Unregister obunachini xaritadan olib tashlaydi. Chiqmasdan qayta ro'yxatdan o'tish — xato (MultipleSubscriberException yuz beradi). Fragment uchun onStart() da ro'yxatdan o'ting va onStop() da chiqing. Service uchun — onCreate() va onDestroy() da. ViewModel uchun tavsiya etilmaydi — LiveData dan foydalaning.
Sticky event — yuborilgandan so'ng EventBus da saqlanadigan hodisa. postSticky() dan keyin ro'yxatdan o'tgan yangi obunachilar darhol mos keladigan turdagi oxirgi sticky-hodisani oladi. Bu boshlang'ich holatni uzatish uchun qulay: ekran ochilganda, u ro'yxatdan o'tishidan oldin yuborilgan oxirgi ma'lumotlarni oladi. Sticky-hodisani EventBus.getDefault().removeStickyEvent(Class) orqali o'chirish mumkin.
ThreadMode ishlovchi qaysi oqimda chaqirilishini belgilaydi. POSTING (odatiy) — ishlovchi post chaqirilgan bir xil oqimda bajariladi. MAIN — ishlovchi main oqimida Handler orqali bajariladi. BACKGROUND — ishlovchi background oqimida bajariladi; agar post main oqimida chaqirilgan bo'lsa, EventBus ishlovchini background oqim navbatiga qo'yadi. ASYNC — har bir ishlovchi oqimlar hovuzidan alohida background oqimida bajariladi. UI yangilanishlari uchun MAIN dan foydalaning.
// Sticky Event
data class LocationEvent(val lat: Double, val lng: Double)
// LocationService dan sticky-hodisani yuborish
EventBus.getDefault().postSticky(LocationEvent(55.7558, 37.6173))
// Obunachi ro'yxatdan o'tgandan so'ng darhol oxirgi joylashuvni oladi
class MapFragment : Fragment() {
override fun onStart() {
super.onStart()
EventBus.getDefault().register(this)
// Agar postSticky bo'lgan bo'lsa, darhol LocationEvent oladi
}
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-hodisani o'chirish
EventBus.getDefault().removeStickyEvent(LocationEvent::class.java)
BACKGROUND barcha ishlovchilar uchun bitta background oqimidan foydalanadi — ular ketma-ket bajariladi. ASYNC har bir ishlovchi uchun hovuzdan yangi oqim yaratadi — ular parallel bajariladi. BACKGROUND umumiy ma'lumotlar bazasi bilan kirish-chiqish operatsiyalari uchun mos. ASYNC — mustaqil uzoq operatsiyalar uchun (tarmoq so'rovlari). Ikkala rejim umumiy resurslarga thread-safe kirishni talab qiladi. Oqimlar soni: ASYNC hovuzi cheklanmagan.
EventBus dan foydalanishda dasturchilar ko'pincha xotira sizib chiqishlari, kutilmagan chaqiruvlar va unumdorlikning pasayishiga olib keladigan xatolarga yo'l qo'yishadi. Eng muhimlari: Activity da unutilgan chiqish, onCreate da ro'yxatdan o'tish (onStart/onStop o'rniga), Object ga obuna bo'lish (barcha hodisalar), cheksiz sikl ichida hodisalar yuborish. Android Profiler orqali profillash muammolarni aniqlashga yordam beradi.
Eng keng tarqalgan xato — onDestroy() da chiqmasdan onCreate() da Activity ni ro'yxatdan o'tkazish. Natija: EventBus Activity ga havolani saqlaydi, GC uni bo'shata olmaydi. Ekran aylantirilganda yangi Activity yaratiladi, oldingisi xotirada qoladi. Yechim: har doim register/unregister ni onStart/onStop da juftlang. Fragment uchun xuddi shu sxemadan foydalaning. Agar Activity finish dan keyin EventBus tomonidan ushlab turilsa, Memory Profiler orqali tekshiring.
Subscriber Index siz EventBus har bir register() da @Subscribe metodlarini topish uchun refleksiyadan foydalanadi. Android 6-7 qurilmalarida refleksiya sekin ishlaydi, 50 ms gacha kechikishlarga sabab bo'ladi. Subscriber Index refleksiyani butunlay bartaraf qiladi: metodlar annotatsiya protsessori orqali kompilyatsiya bosqichida indekslanadi. 20+ obunachisi bo'lgan loyihalar uchun indeks majburiy. build.gradle da kapt yoki annotationProcessor ulanganligini tekshiring.
// build.gradle (app) — Subscriber Index ni ulash
dependencies {
implementation 'org.greenrobot:eventbus:3.3.1'
annotationProcessor 'org.greenrobot:eventbus-annotation-processor:3.3.1'
}
// Kotlin uchun kapt dan foydalaning
plugins {
id 'kotlin-kapt'
}
dependencies {
implementation 'org.greenrobot:eventbus:3.3.1'
kapt 'org.greenrobot:eventbus-annotation-processor:3.3.1'
}
// Indeks konfiguratsiyasi (defaultConfig da)
kapt {
arguments {
arg('eventBusIndex', 'com.app.EventBusIndex')
}
}
Kotlin va Jetpack Compose dagi zamonaviy loyihalar kotlinx.coroutines kutubxonasidan SharedFlow va Channel ni afzal ko'radi. SharedFlow replay (sticky), buffering va backpressure ni qo'llab-quvvatlaydi. Channel — bir martalik hodisalar (toast, navigatsiya). Ikkala yechim repeatOnLifecycle orqali Lifecycle bilan integratsiyalangan va qo'lda chiqishni talab qilmaydi. Yangi loyihalar uchun EventBus o'rniga SharedFlow tavsiya etiladi. Mavjud loyihalar uchun migratsiya refaktoring vaqtida maqsadga muvofiq.
Tez-tez so'raladigan savollar
EventBus har qanday komponentlar (Activity, Fragment, Service) o'rtasida ma'lumot almashish uchun hodisalar shinasi. LiveData UI komponenti tomonidan kuzatiladigan ma'lumotlar uchun lifecycle-aware o'ram. LiveData Lifecycle orqali obunani avtomatik boshqaradi. EventBus qo'lda register/unregister talab qiladi. LiveData UI qatlami uchun tavsiya etiladi, EventBus — LiveData noqulay bo'lgan modullararo aloqa uchun.
Sticky event — yuborilgandan so'ng EventBus da saqlanadigan hodisa. postSticky() dan keyin ro'yxatdan o'tgan yangi obunachilar darhol oxirgi sticky-hodisani oladi. Boshlang'ich holat uchun ishlatiladi: ekran ochilganda takroriy so'rovsiz oxirgi ma'lumotlarni oladi. removeStickyEvent() yoki xuddi shu turdagi yangi sticky-hodisa yuborilganda o'chiriladi.
Ha, EventBus thread-safe. post() chaqiruvi istalgan oqimdan mumkin. Hodisaning obunachilarga yetkazilishi kutubxona ichida sinxronlashtiriladi. ThreadMode ishlovchining bajarilish oqimini belgilaydi: MAIN (main oqimi Handler orqali), POSTING (jo'natuvchi oqimi), BACKGROUND (fon vazifalari navbati), ASYNC (alohida oqim). UI yangilanishlari uchun MAIN, og'ir operatsiyalar uchun ASYNC dan foydalaning.
EventBus.builder().logNoSubscriberMessages(true).sendNoSubscriberEvent(true).install() orqali loglashni yoqing. Ishlovchisiz hodisalarni kuzatish uchun NoSubscriberEvent ga obuna bo'ling. Global istisnolarni boshqarish uchun SubscriberExceptionEvent dan foydalaning. Android Profiler sizib chiqishlarni topishga yordam beradi. Murakkab stsenariylar uchun test yozing: EventBus.getDefault().register(mock) + post(event) + verify(mock).
Yo'q, EventBus (GreenRobot) Android SDK va JVM ga bog'langan. Kotlin Multiplatform uchun Kotlin Multiplatform SharedFlow yoki KMMBus — umumiy kodni qo'llab-quvvatlovchi kutubxonalardan foydalaning. EventBus KMM loyihasining Android tomonida ishlaydi, lekin commonMain da mavjud emas. Cross-platform hodisalar uchun platformaning native mexanizmlari yoki expect/actual orqali abstraktsiya afzal.
Xulosa
Biz kalit topshirig'i bilan mobil ilovani ishlab chiqamiz
IT Sectr 2017-yildan beri startaplar va korxonalar uchun iOS va Android ilovalarini yaratadi. Biz sizga maslahat beramiz va eng yaxshi yechimni taklif qilamiz.