EventBus adalah pustaka untuk Android yang mengimplementasikan pola Publisher-Subscriber melalui bus peristiwa, memungkinkan pertukaran data antar komponen tanpa ketergantungan langsung. Dikembangkan oleh GreenRobot, pustaka ini menyederhanakan komunikasi antara Activity, Fragment, Service dan Background Thread. Menurut data GitHub (2025), EventBus memiliki lebih dari 25 ribu bintang dan digunakan di ribuan aplikasi Android. Operasi utama — subscribe (berlangganan peristiwa), post (mengirim peristiwa) dan sticky event (peristiwa tertunda untuk pelanggan baru).
Poin utama
EventBus adalah pustaka bus peristiwa untuk Android yang mengimplementasikan pola Publisher-Subscriber (penerbit-pelanggan). Ini memungkinkan pengiriman peristiwa antar komponen aplikasi (Activity, Fragment, Service, ViewModel) tanpa membuat ketergantungan eksplisit di antaranya. Berbeda dengan mekanisme standar Android (Intent, BroadcastReceiver), EventBus bekerja di dalam proses dan tidak menggunakan IPC. Pustaka ini dioptimalkan untuk kinerja dan tidak menggunakan refleksi ketika Subscriber Index dikonfigurasi dengan benar.
Arsitektur EventBus terdiri dari tiga elemen kunci: Event (kelas POJO dengan data), Subscriber (objek dengan metode yang ditandai @Subscribe) dan EventBus (dispatcher pusat). Pelanggan mendaftar melalui EventBus.getDefault().register(this), berhenti berlangganan — melalui unregister(this). Peristiwa diketik: penangan berlangganan ke kelas peristiwa tertentu dan hanya dipanggil saat post peristiwa dari kelas ini atau subkelasnya.
// Peristiwa POJO
data class MessageEvent(
val message: String,
val timestamp: Long = System.currentTimeMillis()
)
// Pelanggan di Activity
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
}
}
// Mengirim peristiwa dari komponen lain
EventBus.getDefault().post(MessageEvent("Hello from Service"))
Secara default, EventBus menggunakan refleksi untuk menemukan metode @Subscribe saat register(). Subscriber Index menghasilkan indeks penangan pada tahap kompilasi melalui pemroses anotasi. Ini menghilangkan overhead refleksi dan mempercepat pendaftaran. Untuk mengaktifkan, tambahkan eventbus-annotation-processor ke build.gradle. EventBus secara otomatis menggunakan indeks jika tersedia di classpath. Tanpa indeks, pustaka masih berfungsi, tetapi dengan penurunan kinerja ringan.
Saat memanggil EventBus.getDefault().post(event), pustaka menentukan tipe peristiwa, menemukan semua pelanggan terdaftar dengan metode @Subscribe yang menerima tipe ini, dan memanggilnya sesuai ThreadMode yang ditentukan. Pencarian pelanggan dilakukan melalui peta Class → CopyOnWriteArrayList
Pelanggan harus mendaftar di onStart() dan berhenti berlangganan di onStop(). Jika mendaftar di onCreate() dan berhenti di onDestroy(), Activity yang dihancurkan tanpa memanggil onDestroy (karena finish()) dapat tetap berada di daftar pelanggan. Kebocoran pelanggan — salah satu masalah utama EventBus: Activity yang tersisa di daftar pelanggan tidak akan dikumpulkan oleh GC sampai berhenti berlangganan. Selalu pasangkan register/unregister di metode lifecycle yang benar.
Anotasi @Subscribe mendukung parameter priority (bilangan bulat, default 0). Penangan dengan prioritas lebih tinggi dipanggil lebih awal. cancelEventDelivery() memungkinkan menghentikan pengiriman peristiwa ke pelanggan lainnya. Ini berguna untuk penangan prioritas (logging, otentikasi) yang dapat membatalkan pemrosesan peristiwa oleh pelanggan yang lebih rendah. Fungsi hanya tersedia di thread pengiriman peristiwa.
// Contoh kompleks dengan prioritas
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)
}
}
// Mengirim peristiwa
EventBus.getDefault().post(NavigationEvent("profile", bundle))
Android menawarkan beberapa mekanisme untuk komunikasi intra-proses: EventBus, LocalBroadcastManager (usang) dan LiveData/Flow. Masing-masing memiliki kelebihan dan kekurangan. Pilihan tergantung pada pendekatan arsitektur dan persyaratan kinerja. Rekomendasi modern Google cenderung ke LiveData dan Flow karena integrasi dengan Lifecycle dan tidak adanya kebocoran.
| Karakteristik | EventBus | LocalBroadcastManager | LiveData / Flow |
|---|---|---|---|
| Pengetikan | Melalui kelas peristiwa | Melalui Intent filter (String) | Melalui tipe generik |
| Lifecycle-aware | Tidak (berhenti manual) | Tidak (berhenti manual) | Ya (otomatis) |
| Sticky | Ya (postSticky) | Tidak | Ya (LiveData — selalu sticky) |
| ThreadMode | MAIN, POSTING, BACKGROUND, ASYNC | Hanya main | Melalui observe/observeOn |
| Kinerja | Tinggi (Subscriber Index) | Sedang (pembungkus IPC) | Tinggi (observasi) |
EventBus berguna dalam proyek dengan kode warisan (legacy code) dan di mana LiveData/Flow tidak tersedia (proyek Java-only). Sticky events EventBus memberikan fleksibilitas yang tidak dimiliki LocalBroadcastManager. EventBus juga lebih sederhana untuk mengirim peristiwa dari Service ke Activity tanpa ViewModel — terutama saat perlu memberi tahu tentang kemajuan tugas latar belakang. Pustaka ini memiliki ukuran minimal (sekitar 50 KB) dan tidak menambahkan ketergantungan.
LiveData dan Flow adalah bagian dari Android Jetpack dan terintegrasi dengan Lifecycle. Mereka secara otomatis berhenti berlangganan saat komponen dihancurkan, menghilangkan kebocoran memori. Flow mendukung coroutine dan operator transformasi kompleks. Google merekomendasikan LiveData untuk lapisan UI dan Flow untuk repositori. EventBus tetap untuk peristiwa lintas-modul di mana navigasi dan logika bisnis tidak cocok dengan MVVM.
Subscribe — pendaftaran penangan peristiwa melalui anotasi @Subscribe. Metode harus public, void dan menerima tepat satu parameter — tipe peristiwa. Post — mengirim peristiwa ke semua penangan yang berlangganan melalui EventBus.getDefault().post(event). Metode post tidak mengembalikan hasil dan tidak memberi tahu berapa banyak penangan yang dipanggil. Untuk peristiwa dengan jawaban, gunakan kelas Event terpisah dengan bidang untuk hasil.
Peristiwa — kelas Java/Kotlin apa pun. Disarankan menggunakan data class untuk peristiwa yang tidak dapat diubah dan kelas biasa untuk peristiwa dengan bidang yang dapat diubah. Penamaan peristiwa harus mencerminkan tindakan: UserLoggedInEvent, DataLoadedEvent, NetworkErrorEvent. Hindari satu kelas Event umum dengan bidang String type — ini menghilangkan keuntungan pengetikan. Hierarki peristiwa (Event induk) memungkinkan berlangganan ke sekelompok peristiwa terkait.
// Hierarki peristiwa
open class UserEvent
data class UserLoggedIn(val userId: String) : UserEvent()
data class UserLoggedOut(val reason: String) : UserEvent()
// Berlangganan ke kelas dasar
class SessionManager {
@Subscribe(threadMode = ThreadMode.MAIN)
fun onUserEvent(event: UserEvent) {
when (event) {
is UserLoggedIn -> startSession(event.userId)
is UserLoggedOut -> endSession(event.reason)
}
}
}
// Mengirim
EventBus.getDefault().post(UserLoggedIn("user_123"))
Pemanggilan EventBus.getDefault().register(this) memindai kelas pelanggan melalui refleksi atau Subscriber Index dan menyimpan metode @Subscribe yang ditemukan di peta peristiwa. Unregister menghapus pelanggan dari peta. Mendaftar ulang tanpa berhenti berlangganan — kesalahan (MultipleSubscriberException akan terjadi). Untuk Fragment, daftar di onStart() dan berhenti di onStop(). Untuk Service — di onCreate() dan onDestroy(). Untuk ViewModel tidak disarankan — gunakan LiveData.
Sticky event — peristiwa yang disimpan di EventBus setelah dikirim. Pelanggan baru yang mendaftar setelah postSticky() segera menerima sticky-peristiwa terakhir dari tipe yang sesuai. Ini nyaman untuk mengirimkan status awal: saat membuka layar, ia menerima data terakhir yang dikirim sebelum pendaftarannya. Menghapus sticky-peristiwa dapat dilakukan melalui EventBus.getDefault().removeStickyEvent(Class).
ThreadMode menentukan di thread mana penangan dipanggil. POSTING (default) — penangan dijalankan di thread yang sama tempat post dipanggil. MAIN — penangan dijalankan di main thread melalui Handler. BACKGROUND — penangan dijalankan di background thread; jika post dipanggil di main thread, EventBus menempatkan penangan di antrian background thread. ASYNC — setiap penangan dijalankan di background thread terpisah dari kumpulan thread. Untuk pembaruan UI, gunakan MAIN.
// Sticky Event
data class LocationEvent(val lat: Double, val lng: Double)
// Mengirim sticky-peristiwa dari LocationService
EventBus.getDefault().postSticky(LocationEvent(55.7558, 37.6173))
// Pelanggan menerima lokasi terakhir segera setelah pendaftaran
class MapFragment : Fragment() {
override fun onStart() {
super.onStart()
EventBus.getDefault().register(this)
// Segera akan menerima LocationEvent jika ada postSticky
}
override fun onStop() {
EventBus.getDefault().unregister(this)
super.onStop()
}
@Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
fun onLocationEvent(event: LocationEvent) {
moveMapTo(event.lat, event.lng)
}
}
// Menghapus sticky-peristiwa
EventBus.getDefault().removeStickyEvent(LocationEvent::class.java)
BACKGROUND menggunakan satu background-thread untuk semua penangan — mereka dijalankan secara berurutan. ASYNC membuat thread baru dari kumpulan untuk setiap penangan — mereka dijalankan secara paralel. BACKGROUND cocok untuk operasi input-output dengan database bersama. ASYNC — untuk operasi panjang independen (permintaan jaringan). Kedua mode memerlukan akses thread-safe ke sumber daya bersama. Jumlah thread: kumpulan ASYNC tidak terbatas.
Saat menggunakan EventBus, pengembang sering membuat kesalahan yang menyebabkan kebocoran memori, panggilan tak terduga dan penurunan kinerja. Yang paling kritis: lupa berhenti berlangganan di Activity, pendaftaran di onCreate (bukan onStart/onStop), berlangganan ke Object (semua peristiwa), mengirim peristiwa dalam loop tak terbatas. Profiling melalui Android Profiler membantu mengidentifikasi masalah.
Kesalahan paling umum — pendaftaran Activity di onCreate() tanpa berhenti berlangganan di onDestroy(). Hasil: EventBus menyimpan referensi ke Activity, GC tidak dapat membebaskannya. Saat memutar layar, Activity baru dibuat, yang sebelumnya tetap di memori. Solusi: selalu pasangkan register/unregister di onStart/onStop. Untuk Fragment, gunakan skema yang sama. Jika Activity ditahan oleh EventBus setelah finish, periksa melalui Memory Profiler.
Tanpa Subscriber Index, EventBus menggunakan refleksi untuk menemukan metode @Subscribe di setiap register(). Pada perangkat Android 6-7, refleksi bekerja lambat, menyebabkan penundaan hingga 50 ms. Subscriber Index sepenuhnya menghilangkan refleksi: metode diindeks pada tahap kompilasi melalui pemroses anotasi. Untuk proyek dengan 20+ pelanggan, indeks wajib. Periksa apakah kapt atau annotationProcessor terhubung di build.gradle.
// build.gradle (app) — menghubungkan Subscriber Index
dependencies {
implementation 'org.greenrobot:eventbus:3.3.1'
annotationProcessor 'org.greenrobot:eventbus-annotation-processor:3.3.1'
}
// Untuk Kotlin gunakan kapt
plugins {
id 'kotlin-kapt'
}
dependencies {
implementation 'org.greenrobot:eventbus:3.3.1'
kapt 'org.greenrobot:eventbus-annotation-processor:3.3.1'
}
// Konfigurasi indeks (di defaultConfig)
kapt {
arguments {
arg('eventBusIndex', 'com.app.EventBusIndex')
}
}
Proyek modern di Kotlin dan Jetpack Compose lebih memilih SharedFlow dan Channel dari pustaka kotlinx.coroutines. SharedFlow mendukung replay (sticky), buffering dan backpressure. Channel — peristiwa sekali pakai (toast, navigasi). Kedua solusi terintegrasi dengan Lifecycle melalui repeatOnLifecycle dan tidak memerlukan penghentian langganan manual. Untuk proyek baru, SharedFlow direkomendasikan daripada EventBus. Untuk proyek yang ada, migrasi dibenarkan saat refactoring.
Pertanyaan yang sering diajukan
EventBus adalah bus peristiwa untuk pertukaran data antar komponen mana pun (Activity, Fragment, Service). LiveData adalah pembungkus lifecycle-aware untuk data yang diamati oleh komponen UI. LiveData secara otomatis mengelola langganan melalui Lifecycle. EventBus memerlukan register/unregister manual. LiveData direkomendasikan untuk lapisan UI, EventBus — untuk komunikasi lintas-modul di mana LiveData tidak nyaman.
Sticky event — peristiwa yang disimpan di EventBus setelah dikirim. Pelanggan baru yang mendaftar setelah postSticky() segera menerima sticky-peristiwa terakhir. Digunakan untuk status awal: saat membuka layar, ia menerima data terakhir tanpa permintaan berulang. Dihapus melalui removeStickyEvent() atau saat mengirim sticky-peristiwa baru dari tipe yang sama.
Ya, EventBus thread-safe. Panggilan post() dimungkinkan dari thread mana pun. Pengiriman peristiwa ke pelanggan disinkronkan di dalam pustaka. ThreadMode menentukan thread eksekusi penangan: MAIN (main thread melalui Handler), POSTING (thread pengirim), BACKGROUND (antrian tugas latar belakang), ASYNC (thread terpisah). Untuk pembaruan UI gunakan MAIN, untuk operasi berat — ASYNC.
Aktifkan logging melalui EventBus.builder().logNoSubscriberMessages(true).sendNoSubscriberEvent(true).install(). Berlangganan ke NoSubscriberEvent untuk melacak peristiwa tanpa penangan. Gunakan SubscriberExceptionEvent untuk penanganan pengecualian global. Android Profiler membantu menemukan kebocoran. Untuk skenario kompleks, tulis tes: EventBus.getDefault().register(mock) + post(event) + verify(mock).
Tidak, EventBus (GreenRobot) terikat pada Android SDK dan JVM. Untuk Kotlin Multiplatform, gunakan Kotlin Multiplatform SharedFlow atau KMMBus — pustaka yang mendukung kode bersama. EventBus di sisi Android proyek KMM berfungsi, tetapi tidak tersedia di commonMain. Untuk peristiwa lintas-platform, mekanisme asli platform atau abstraksi melalui expect/actual lebih disukai.
Kesimpulan
Kami akan mengembangkan aplikasi seluler turnkey
IT Sectr membuat aplikasi iOS dan Android untuk startup dan bisnis sejak 2017. Kami akan memberi saran dan mengusulkan solusi terbaik.
Baca juga