原文地址:【開源庫推薦】#3 Android EventBus的使用 | Stars-One的雜貨小窩
Event bus for Android and Java that simplifies communication between Activities, Fragments, Threads, Services, etc. Less code, better quality
Android和Java的事件總線,簡化了活動,片段,線程,服務等之間的通信。代碼越少,質量越好
EventBus是一款事件分發框架,可以跨進程,跨Activity/Fragment進行通信,今天來簡單的來入下門
介紹
EventBus可以做什么?
這里來個例子比較好說明,我們知道Android中有個廣播機制,可以讓Activity和Service互相通信,但是寫法過於麻煩,且不夠靈活;
又比如,一個Activity中含有幾個Fragment,其中的Fragment互相又要實現傳數據通信,同時,也要與外層的Activity進行數據的交互,按照常規套路,我們使用傳參,寫法十分復雜
這個時候,我們就可以使用EventBus,就可以十分快速且簡單地實現我們需要實現的效果
本質上,EventBus也是使用了觀察者模式來實現其的功能
基本使用
1.綁定Activity
首先,導入依賴
implementation 'org.greenrobot:eventbus:3.0.0'
- 需要在Activity中的
onCreate()
方法中,與當前Activity綁定 - 在Activity的
onDestroy()
方法中,進行解綁,否則會造成內存泄漏問題
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_event_bus)
//綁定
EventBus.getDefault().register(this)
}
override fun onDestroy() {
super.onDestroy()
//取消綁定
EventBus.getDefault().unregister(this)
}
Activity的界面比較簡單,就是一個TextView
和FrameLayout
,之后創建一個Fragment
放入FrameLayout
中
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".EventBusActivity">
<TextView
android:id="@+id/tvContent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textSize="20sp"
android:text="Hello world" />
<FrameLayout
android:id="@+id/framelayout"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
2.聲明入口方法
在當前的綁定的Activity中聲明一個public的方法,返回值為void,同時,使用EventBus的注解@Subscribe
對方法進行標識
注:此注解是
3.0.0版本
以后才加的,且方法一定是要公共的,否則EventBus會報錯,原因也是很簡單,估計EventBus是通過注解去找到方法,之后利用Java的反射特性進行回調
@Subscribe(threadMode = ThreadMode.MAIN)
public fun changeText(str:String){
tvContent.text = str
}
threadMode
有四種模式:
POSTING
(默認):如果使用事件處理函數指定了線程模型為POSTING,那么該事件在哪個線程發布出來的,事件處理函數就會在這個線程中運行,也就是說發布事件和接收事件在同一個線程。在線程模型為POSTING的事件處理函數中盡量避免執行耗時操作,因為它會阻塞事件的傳遞,甚至有可能會引起應用程序無響應(ANR)。MAIN
:事件的處理會在UI線程中執行。事件處理時間不能太長,長了會ANR的。BACKGROUND
:如果事件是在UI線程中發布出來的,那么該事件處理函數就會在新的線程中運行,如果事件本來就是子線程中發布出來的,那么該事件處理函數直接在發布事件的線程中執行。在此事件處理函數中禁止進行UI更新操作。ASYNC
:無論事件在哪個線程發布,該事件處理函數都會在新建的子線程中執行,同樣,此事件處理函數中禁止進行UI更新操作。
這里我們選用Main
.且為了簡單起見,方法定義一個String類型,之后把activity中的文本修改為傳過來的數據
這個方法其實就是事件的接收者,之后在其他地方(如Fragment,Service或其他Activity)發出事件,EventBus會根據參數類型尋找對應的入口,同時將數據傳到當前的入口,我將其稱為入口方法
方法類型可以隨意定義,一般是某個事件定義個類用來存儲傳過來的數據,規范一點的話,可以統一下事件類中的格式,使用枚舉來區分不同事件(當然,這種就比較適合那種只有一個入口)
3.post()
方法發事件
之后我們在其他調用post
方法發出事件即可,這里給大家演示下載Fragment中的按鈕發出事件
btnChangeText.setOnClickListener {
EventBus.getDefault().post("修改過后的文字")
}
之后即可實現點擊按鈕實現改變文字的效果,如下圖
補充-postSticky()
方法
上述中,使用的post()
方法,但是可以看到代碼提示中還存在一個postSticky()
方法,這個方法是由什么區別呢?
postSticky()
是對應的粘性事件,我們可以看到Subscribe
注解中存在一個sticky
屬性,其默認是false
看到這就可以猜測到了,這兩者是配合使用的
那么什么是粘性事件呢?
比如說你發出了一個事件,但是由於對應的事件消費的Activity或Fragment對象還沒有被創建,於是你發出的事件就會被丟棄了
為了避免這種情況,EventBus提供了粘性事件,它會把事件先存在隊列中,等待Activity或Fragment啟動,則會自動把事件分發過去
postSticky()
的使用與post()
一樣,這里不再贅述
插件推薦
由於使用了EventBus,排查代碼的時候非常不好排查,這里推薦大家一款Android Studio的插件,可以快速跳轉到對應的入口方法或是發出方法的代碼
名字為EventBus3-IDEA
安裝之后,你就可以看見旁邊會有個小圖標,點擊之后會跳轉到對應的代碼
不過測試的時候感覺對Kotlin語言還沒適配,點擊沒法跳轉,等作者等后續適配...