如何進(jìn)行網(wǎng)站維護(hù)seo云優(yōu)化如何
一、概念
EventBus是一款在 Android 開發(fā)中使用的發(fā)布-訂閱事件總線框架,基于觀察者模式,將事件的接收者和發(fā)送者解耦,簡化了組件之間的通信,使用簡單、效率高、體積小。
一句話:用于Android組件間通信的。
二、原理
三、簡單使用
- 在app module的builde.gradle文件中導(dǎo)入依賴庫:
implementation 'org.greenrobot:eventbus:3.3.1'
- 配置混淆
-keepattributes *Annotation*
-keepclassmembers class * {@org.greenrobot.eventbus.Subscribe <methods>;
}
-keep enum org.greenrobot.eventbus.ThreadMode { *; }# Only required if you use AsyncExecutor
-keepclassmembers class * extends org.greenrobot.eventbus.util.ThrowableFailureEvent {<init>(java.lang.Throwable);
}
1、訂閱者EventBusService后臺注冊,前臺EventBusActivity 發(fā)送的數(shù)據(jù)。注冊以后一定要記得解注冊,否則會內(nèi)存泄漏。onMsgEventReceived
是接收消息的方法,該方法定義需要注意:
- 該方法有且僅有一個參數(shù);
- 必須用
public
修飾,不能使用static
或者abstract
; - 需要添加
@Subscribe()
注解;
public class EventBusService extends Service {private static final String TAG = "Test_EventBusService";@Overridepublic void onCreate() {super.onCreate();//注冊數(shù)據(jù)監(jiān)聽EventBus.getDefault().register(this);}@Nullable@Overridepublic IBinder onBind(Intent intent) {return null;}@Subscribepublic void onMsgEventReceived(String msg) {Log.i(TAG, "String msg: " + msg);}@Subscribe(threadMode = ThreadMode.MAIN, sticky = true, priority = 1)public void onMsgEventReceived(MsgEvent event) {Log.i(TAG, "MsgEvent msg: " + event.getMsg());}@Overridepublic void onDestroy() {super.onDestroy();//解注冊數(shù)據(jù)監(jiān)聽EventBus.getDefault().unregister(this);}
}
2、前臺Activity在按鈕點擊的時候發(fā)送信息到后臺Service。
public class EventBusActivity extends AppCompatActivity {private static final String TAG = "Test_EventBusActivity";@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_event_bus);Button msg1Btn = findViewById(R.id.btn1);Button msg2Btn = findViewById(R.id.btn2);msg1Btn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {//發(fā)送數(shù)據(jù)給監(jiān)聽者EventBus.getDefault().post("msg1 - coming!!!");}});msg2Btn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {//發(fā)送數(shù)據(jù)給監(jiān)聽者MsgEvent event = new MsgEvent("msg2 - coming!!!");EventBus.getDefault().post(event);}});}@Overrideprotected void onDestroy() {super.onDestroy();}
}
3、MsgEvent數(shù)據(jù)類型。
public class MsgEvent {private String msg;public MsgEvent(String msg) {this.msg = msg;}public String getMsg() {return msg;}public void setMsg(String msg) {this.msg = msg;}@Overridepublic String toString() {return "MsgEvent{" +"msg='" + msg + '\'' +'}';}
}
4、運(yùn)行結(jié)果
四、Subscribe注解
Subscribe是EventBus自定義的注解,共有三個參數(shù)(可選):ThreadMode
、boolean sticky
、int priority
。
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true, priority = 1)
public void onMsgEventReceived(MsgEvent event) {Toast.makeText(this, event.getMsg(), Toast.LENGTH_LONG).show();
}
1、ThreadMode取值:
- ThreadMode.POSTING:默認(rèn)的線程模式,在哪個線程發(fā)送事件就在對應(yīng)線程處理事件。避免了線程切換,效率高。
代碼測試:
#EventBusActivity
msg1Btn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {//發(fā)送數(shù)據(jù)給監(jiān)聽者new Thread(new Runnable() {@Overridepublic void run() {Log.i(TAG, "post thread: " + Thread.currentThread().getName());EventBus.getDefault().post("msg1 - coming!!!");}}).start();}});#EventBusService
@Subscribe
public void onMsgEventReceived(String msg) {Log.i(TAG, "onMsgEventReceived thread: " + Thread.currentThread().getName());Log.i(TAG, "String msg: " + msg);
}
把post
的動作放到子線程中,結(jié)果如下,在哪個線程發(fā)送,就會在哪個線程執(zhí)行:
- ThreadMode.MAIN:如在主線程(UI線程)發(fā)送事件,則直接在主線程處理事件;如果在子線程發(fā)送事件,則先將事件入隊列,然后通過
Handler
切換到主線程,依次處理事件。
該模式下,在主線程(UI線程)發(fā)送事件,則直接在主線程處理事件,如果處理方法中有耗時操作就會堵塞進(jìn)程。
代碼測試1:
#EventBusActivity
msg1Btn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {//發(fā)送數(shù)據(jù)給監(jiān)聽者new Thread(new Runnable() {@Overridepublic void run() {Log.i(TAG, "post thread: " + Thread.currentThread().getName());EventBus.getDefault().post("msg1 - coming!!!");}}).start();}});#EventBusService
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMsgEventReceived(String msg) {Log.i(TAG, "onMsgEventReceived thread: " + Thread.currentThread().getName());Log.i(TAG, "String msg: " + msg);
}
發(fā)送post
代碼放到子線程中,處理事件代碼加上ThreadMode.MAIN
注解參數(shù),結(jié)果如下,可以用在子線程處理耗時操作,然后返回值需要切回到主線程刷新UI的場景:
代碼測試2:
#EventBusActivity
msg1Btn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {//發(fā)送數(shù)據(jù)給監(jiān)聽者Log.i(TAG, "post thread: " + Thread.currentThread().getName());EventBus.getDefault().post("msg1 - coming!!!");Log.i(TAG, "post thread: " + Thread.currentThread().getName());EventBus.getDefault().post("msg1-1 - coming!!!");}});#EventBusService
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMsgEventReceived(String msg) {Log.i(TAG, "onMsgEventReceived thread: " + Thread.currentThread().getName());Log.i(TAG, "String msg: " + msg);try {Thread.sleep(2 * 1000);} catch (InterruptedException e) {e.printStackTrace();}
}
發(fā)送post
放在主線程并連續(xù)發(fā)送兩次,接收事件的函數(shù)加上耗時操作,運(yùn)行結(jié)果如下,兩次post
打印就相隔2s,第二次post
需要等第一次事件接收處理完以后才能發(fā)出,所以主線程會阻塞:
同樣修改下發(fā)出post
的代碼放到子線程后沒有這個問題,結(jié)果如下:
- ThreadMode.MAIN_ORDERED:無論在那個線程發(fā)送事件,都先將事件入隊列,然后通過
Handler
切換到主線程,依次處理事件。
代碼測試:
#EventBusActivity
msg1Btn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {//發(fā)送數(shù)據(jù)給監(jiān)聽者Log.i(TAG, "post thread: " + Thread.currentThread().getName());EventBus.getDefault().post("msg1 - coming!!!");Log.i(TAG, "post thread: " + Thread.currentThread().getName());EventBus.getDefault().post("msg1-1 - coming!!!");}});#EventBusService
@Subscribe(threadMode = ThreadMode.MAIN_ORDERED)
public void onMsgEventReceived(String msg) {Log.i(TAG, "onMsgEventReceived thread: " + Thread.currentThread().getName());Log.i(TAG, "String msg: " + msg);try {Thread.sleep(2 * 1000);} catch (InterruptedException e) {e.printStackTrace();}
}
代碼和ThreadMode.MAIN
測試2一樣,只是將threadMode
改為了MAIN_ORDERED
,運(yùn)行結(jié)果如下,兩次post
可以連續(xù)發(fā)出:
- ThreadMode.BACKGROUND:如果在主線程發(fā)送事件,則先將事件入隊列,然后通過線程池依次處理事件;如果在子線程發(fā)送事件,則直接在發(fā)送事件的子線程處理事件。
代碼測試1:
msg1Btn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {//發(fā)送數(shù)據(jù)給監(jiān)聽者Log.i(TAG, "post thread: " + Thread.currentThread().getName());EventBus.getDefault().post("msg1 - coming!!!");}});#EventBusService
@Subscribe(threadMode = ThreadMode.BACKGROUND)
public void onMsgEventReceived(String msg) {Log.i(TAG, "onMsgEventReceived thread: " + Thread.currentThread().getName());Log.i(TAG, "String msg: " + msg);
}
運(yùn)行結(jié)果如下,主線程發(fā)送事件,線程池依次處理事件:
代碼測試2:
msg1Btn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {//發(fā)送數(shù)據(jù)給監(jiān)聽者new Thread(new Runnable() {@Overridepublic void run() {Log.i(TAG, "post thread: " + Thread.currentThread().getName());EventBus.getDefault().post("msg1 - coming!!!");}}).start();}});#EventBusService
@Subscribe(threadMode = ThreadMode.BACKGROUND)
public void onMsgEventReceived(String msg) {Log.i(TAG, "onMsgEventReceived thread: " + Thread.currentThread().getName());Log.i(TAG, "String msg: " + msg);
}
運(yùn)行結(jié)果,子線程發(fā)送事件,則直接在發(fā)送事件的子線程處理事件:
- ThreadMode.ASYNC:無論在那個線程發(fā)送事件,都將事件入隊列,然后通過線程池處理。
代碼測試1:
msg1Btn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {//發(fā)送數(shù)據(jù)給監(jiān)聽者Log.i(TAG, "post thread: " + Thread.currentThread().getName());EventBus.getDefault().post("msg1 - coming!!!");}});#EventBusService
@Subscribe(threadMode = ThreadMode.ASYNC)
public void onMsgEventReceived(String msg) {Log.i(TAG, "onMsgEventReceived thread: " + Thread.currentThread().getName());Log.i(TAG, "String msg: " + msg);
}
運(yùn)行結(jié)果,主線程發(fā)送,線程池處理:
代碼測試2:
msg1Btn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {//發(fā)送數(shù)據(jù)給監(jiān)聽者new Thread(new Runnable() {@Overridepublic void run() {Log.i(TAG, "post thread: " + Thread.currentThread().getName());EventBus.getDefault().post("msg1 - coming!!!");}}).start();}});#EventBusService
@Subscribe(threadMode = ThreadMode.ASYNC)
public void onMsgEventReceived(String msg) {Log.i(TAG, "onMsgEventReceived thread: " + Thread.currentThread().getName());Log.i(TAG, "String msg: " + msg);
}
運(yùn)行結(jié)果,子線程發(fā)送,線程池處理:
2、sticky:
sticky
是否為粘性監(jiān)聽,boolean類型,默認(rèn)值為false。正常我們都是先訂閱,才能接收到發(fā)出的事件,sticky的作用就是訂閱者可以先不進(jìn)行注冊,事件先發(fā)出,再注冊訂閱者,同樣可以接收到事件,并進(jìn)行處理。
3、priority:
priority
是優(yōu)先級,int類型,默認(rèn)值為0。值越大,優(yōu)先級越高,越優(yōu)先接收到事件。值得注意的是,只有在post
事件和事件接收處理,處于同一個線程環(huán)境的時候,才有意義。
參考文章
EventBus詳解 (詳解 + 原理)