如何進(jìn)行網(wǎng)站維護(hù)seo云優(yōu)化如何
一、概念
EventBus是一款在 Android 開(kāi)發(fā)中使用的發(fā)布-訂閱事件總線框架,基于觀察者模式,將事件的接收者和發(fā)送者解耦,簡(jiǎn)化了組件之間的通信,使用簡(jiǎn)單、效率高、體積小。
一句話:用于Android組件間通信的。
二、原理
三、簡(jiǎn)單使用
- 在app module的builde.gradle文件中導(dǎo)入依賴庫(kù):
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后臺(tái)注冊(cè),前臺(tái)EventBusActivity 發(fā)送的數(shù)據(jù)。注冊(cè)以后一定要記得解注冊(cè),否則會(huì)內(nèi)存泄漏。onMsgEventReceived
是接收消息的方法,該方法定義需要注意:
- 該方法有且僅有一個(gè)參數(shù);
- 必須用
public
修飾,不能使用static
或者abstract
; - 需要添加
@Subscribe()
注解;
public class EventBusService extends Service {private static final String TAG = "Test_EventBusService";@Overridepublic void onCreate() {super.onCreate();//注冊(cè)數(shù)據(jù)監(jiān)聽(tīng)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();//解注冊(cè)數(shù)據(jù)監(jiān)聽(tīng)EventBus.getDefault().unregister(this);}
}
2、前臺(tái)Activity在按鈕點(diǎn)擊的時(shí)候發(fā)送信息到后臺(tái)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)聽(tīng)者EventBus.getDefault().post("msg1 - coming!!!");}});msg2Btn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {//發(fā)送數(shù)據(jù)給監(jiān)聽(tīng)者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自定義的注解,共有三個(gè)參數(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)的線程模式,在哪個(gè)線程發(fā)送事件就在對(duì)應(yīng)線程處理事件。避免了線程切換,效率高。
代碼測(cè)試:
#EventBusActivity
msg1Btn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {//發(fā)送數(shù)據(jù)給監(jiān)聽(tīng)者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
的動(dòng)作放到子線程中,結(jié)果如下,在哪個(gè)線程發(fā)送,就會(huì)在哪個(gè)線程執(zhí)行:
- ThreadMode.MAIN:如在主線程(UI線程)發(fā)送事件,則直接在主線程處理事件;如果在子線程發(fā)送事件,則先將事件入隊(duì)列,然后通過(guò)
Handler
切換到主線程,依次處理事件。
該模式下,在主線程(UI線程)發(fā)送事件,則直接在主線程處理事件,如果處理方法中有耗時(shí)操作就會(huì)堵塞進(jìn)程。
代碼測(cè)試1:
#EventBusActivity
msg1Btn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {//發(fā)送數(shù)據(jù)給監(jiān)聽(tīng)者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é)果如下,可以用在子線程處理耗時(shí)操作,然后返回值需要切回到主線程刷新UI的場(chǎng)景:
代碼測(cè)試2:
#EventBusActivity
msg1Btn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {//發(fā)送數(shù)據(jù)給監(jiān)聽(tīng)者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ù)加上耗時(shí)操作,運(yùn)行結(jié)果如下,兩次post
打印就相隔2s,第二次post
需要等第一次事件接收處理完以后才能發(fā)出,所以主線程會(huì)阻塞:
同樣修改下發(fā)出post
的代碼放到子線程后沒(méi)有這個(gè)問(wèn)題,結(jié)果如下:
- ThreadMode.MAIN_ORDERED:無(wú)論在那個(gè)線程發(fā)送事件,都先將事件入隊(duì)列,然后通過(guò)
Handler
切換到主線程,依次處理事件。
代碼測(cè)試:
#EventBusActivity
msg1Btn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {//發(fā)送數(shù)據(jù)給監(jiān)聽(tīng)者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
測(cè)試2一樣,只是將threadMode
改為了MAIN_ORDERED
,運(yùn)行結(jié)果如下,兩次post
可以連續(xù)發(fā)出:
- ThreadMode.BACKGROUND:如果在主線程發(fā)送事件,則先將事件入隊(duì)列,然后通過(guò)線程池依次處理事件;如果在子線程發(fā)送事件,則直接在發(fā)送事件的子線程處理事件。
代碼測(cè)試1:
msg1Btn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {//發(fā)送數(shù)據(jù)給監(jiān)聽(tīng)者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ā)送事件,線程池依次處理事件:
代碼測(cè)試2:
msg1Btn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {//發(fā)送數(shù)據(jù)給監(jiān)聽(tīng)者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:無(wú)論在那個(gè)線程發(fā)送事件,都將事件入隊(duì)列,然后通過(guò)線程池處理。
代碼測(cè)試1:
msg1Btn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {//發(fā)送數(shù)據(jù)給監(jiān)聽(tīng)者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ā)送,線程池處理:
代碼測(cè)試2:
msg1Btn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {//發(fā)送數(shù)據(jù)給監(jiān)聽(tīng)者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)聽(tīng),boolean類型,默認(rèn)值為false。正常我們都是先訂閱,才能接收到發(fā)出的事件,sticky的作用就是訂閱者可以先不進(jìn)行注冊(cè),事件先發(fā)出,再注冊(cè)訂閱者,同樣可以接收到事件,并進(jìn)行處理。
3、priority:
priority
是優(yōu)先級(jí),int類型,默認(rèn)值為0。值越大,優(yōu)先級(jí)越高,越優(yōu)先接收到事件。值得注意的是,只有在post
事件和事件接收處理,處于同一個(gè)線程環(huán)境的時(shí)候,才有意義。
參考文章
EventBus詳解 (詳解 + 原理)