一、簡介
EventBus是由greenrobot 組織貢獻(xiàn)的一個(gè)Android事件發(fā)布/訂閱輕量級框架皆刺。EventBus是一個(gè)Android端優(yōu)化的publish/subscribe消息總線,簡化了應(yīng)用程序內(nèi)各組件間凌摄、組件與后臺線程間的通信羡蛾。比如請求網(wǎng)絡(luò),等網(wǎng)絡(luò)返回時(shí)通過Handler或Broadcast通知UI锨亏,兩個(gè)Fragment之間需要通過Listener通信痴怨,這些需求都可以通過EventBus實(shí)現(xiàn)忙干。
官網(wǎng)地址:http://greenrobot.org/eventbus/
翻譯:http://blog.csdn.net/poorkick/article/details/55099311
<p></p>
二、添加依賴
compile 'org.greenrobot:eventbus:3.0.0'
三浪藻、解鎖技能
-
EventBus的三要素
- Event:事件捐迫,可以是任意類型的對象。
- Subscriber:事件訂閱者珠移,在EventBus3.0之前消息處理的方法只能限定于onEvent弓乙、onEventMainThread、onEventBackgroundThread和onEventAsync钧惧,他們分別代表四種線程模型暇韧。而在EventBus3.0之后,事件處理的方法可以隨便取名浓瞪,但是需要添加一個(gè)注解@Subscribe懈玻,并且要指定線程模型(默認(rèn)為POSTING)。
- Publisher:事件發(fā)布者乾颁,可以在任意線程任意位置發(fā)送事件涂乌,直接調(diào)用EventBus的post(Object)方法∮⒘耄可以自己實(shí)例化EventBus對象湾盒,但一般使用EventBus.getDefault()就好了,根據(jù)post函數(shù)參數(shù)的類型诅妹,會自動調(diào)用訂閱相應(yīng)類型事件的函數(shù)罚勾。
-
EventBus的四種線程模型(ThreadMode)
- POSTING(默認(rèn)):如果使用事件處理函數(shù)指定了線程模型為POSTING,那么該事件在哪個(gè)線程發(fā)布出來的吭狡,事件處理函數(shù)就會在這個(gè)線程中運(yùn)行尖殃,也就是說發(fā)布事件和接收事件在同一個(gè)線程。在線程模型為POSTING的事件處理函數(shù)中盡量避免執(zhí)行耗時(shí)操作划煮,因?yàn)樗鼤枞录膫鬟f送丰,甚至有可能會引起應(yīng)用程序無響應(yīng)(ANR)。
- MAIN:事件的處理會在UI線程中執(zhí)行弛秋。事件處理時(shí)間不能太長器躏,長了會ANR的。
- BACKGROUND:如果事件是在UI線程中發(fā)布出來的蟹略,那么該事件處理函數(shù)就會在新的線程中運(yùn)行登失,如果事件本來就是子線程中發(fā)布出來的,那么該事件處理函數(shù)直接在發(fā)布事件的線程中執(zhí)行科乎。在此事件處理函數(shù)中禁止進(jìn)行UI更新操作壁畸。
- ASYNC:無論事件在哪個(gè)線程發(fā)布,該事件處理函數(shù)都會在新建的子線程中執(zhí)行,同樣捏萍,此事件處理函數(shù)中禁止進(jìn)行UI更新操作太抓。
-
使用步驟
注冊:EventBus.getDefault().register(this);
解注冊(為防止內(nèi)存泄漏):EventBus.getDefault().unregister(this);
-
構(gòu)造發(fā)送消息類:
public class MessageEvent { public String name; public String password; public MessageEvent(String name, String password) { this.name = name; this.password = password; } }
發(fā)布消息:EventBus.getDefault().post(new MessageEvent("name","password"));
-
接收消息:可以有四種線程模型選擇
@Subscribe(threadMode = ThreadMode.MAIN) public void messageEventBus(MessageEvent event){ tv_result.setText("name:"+event.name+" passwrod:"+event.password); }
-
粘性事件
???之前說的使用方法,都是需要先注冊(register)令杈,再post,才能接受到事件走敌;如果你使用postSticky發(fā)送事件,那么可以不需要先注冊逗噩,也能接受到事件掉丽,也就是一個(gè)延遲注冊的過程。
???普通的事件我們通過post發(fā)送給EventBus异雁,發(fā)送過后之后當(dāng)前已經(jīng)訂閱過的方法可以收到捶障。但是如果有些事件需要所有訂閱了該事件的方法都能執(zhí)行呢?例如一個(gè)Activity纲刀,要求它管理的所有Fragment都能執(zhí)行某一個(gè)事件项炼,但是當(dāng)前我只初始化了3個(gè)Fragment,如果這時(shí)候通過post發(fā)送了事件示绊,那么當(dāng)前的3個(gè)Fragment當(dāng)然能收到锭部。但是這個(gè)時(shí)候又初始化了2個(gè)Fragment,那么我必須重新發(fā)送事件面褐,這兩個(gè)Fragment才能執(zhí)行到訂閱方法拌禾。
???粘性事件就是為了解決這個(gè)問題,通過 postSticky 發(fā)送粘性事件展哭,這個(gè)事件不會只被消費(fèi)一次就消失湃窍,而是一直存在系統(tǒng)中,知道被 removeStickyEvent 刪除掉摄杂。那么只要訂閱了該粘性事件的所有方法坝咐,只要被register 的時(shí)候循榆,就會被檢測到析恢,并且執(zhí)行。訂閱的方法需要添加 sticky = true 屬性秧饮。-
構(gòu)造發(fā)送信息類:
public class StickyEvent { public String msg; public StickyEvent(String msg) { this.msg = msg; } }
發(fā)布消息:EventBus.getDefault().postSticky(new StickyEvent("我是粘性事件"));
-
接收消息:和之前的方法一樣映挂,只是多了一個(gè) sticky = true 的屬性。
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true) public void onEvent(StickyEvent event){ tv_c_result.setText(event.msg); }
-
注冊:
EventBus.getDefault().register(CActivity.this);
-
解注冊:
EventBus.getDefault().removeAllStickyEvents(); EventBus.getDefault().unregister(CActivity.class);
-
四盗尸、舉個(gè)栗子
-
主線程發(fā)送事件:
-
自定義事件(類似定義JavaBean)柑船,包含用戶的姓名和密碼;
public class UserEvent { private String name; private String password; public UserEvent() { } public UserEvent(String name, String password) { this.name = name; this.password = password; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @Override public String toString() { return "UserEvent{" + "name='" + name + '\'' + ", password='" + password + '\'' + '}'; } }
-
在onCreate方法中注冊訂閱者泼各,在onDestroy中解注冊鞍时。
public class MainActivity extends AppCompatActivity { @BindView(R.id.jump) Button mJump; @BindView(R.id.send) Button mSend; @BindView(R.id.tv_result) TextView mTvResult; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ButterKnife.bind(this); //注冊訂閱者 EventBus.getDefault().register(this); } @OnClick({R.id.jump, R.id.send}) public void onViewClicked(View view) { switch (view.getId()) { case R.id.jump: startActivity(new Intent(MainActivity.this, SecActivity.class)); break; case R.id.send: break; } } //定義處理接收的方法 @Subscribe(threadMode = ThreadMode.MAIN) public void userEventBus(UserEvent userEvent){ mTvResult.setText(userEvent.toString()); } @Override protected void onDestroy() { super.onDestroy(); //注銷注冊 EventBus.getDefault().unregister(this); } }
-
在另一個(gè)activity中發(fā)送事件,讓訂閱者能夠接收;
@OnClick({R.id.sendData, R.id.receive}) public void onViewClicked(View view) { switch (view.getId()) { case R.id.sendData: //發(fā)送事件 EventBus.getDefault().post(new UserEvent("Mr.sorrow", "123456")); finish(); break; case R.id.receive: break; } }
-
實(shí)現(xiàn)結(jié)果:
<p>
-
-
發(fā)送粘性事件:
-
MainActivity中發(fā)送粘性事件逆巍;
case R.id.send: EventBus.getDefault().postSticky(new MessageEvent("粘性事件", "urgent")); startActivity(new Intent(MainActivity.this, SecActivity.class)); break;
-
SecActivity中接受注冊并處理及塘;
public class SecActivity extends AppCompatActivity { @BindView(R.id.sendData) Button mSendData; @BindView(R.id.receive) Button mReceive; @BindView(R.id.tv_receive) TextView mTvReceive; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_sec); ButterKnife.bind(this); } @OnClick({R.id.sendData, R.id.receive}) public void onViewClicked(View view) { switch (view.getId()) { case R.id.sendData: //發(fā)送事件 EventBus.getDefault().post(new UserEvent("Mr.sorrow", "123456")); finish(); break; case R.id.receive: //要接收時(shí)開始注冊 EventBus.getDefault().register(SecActivity.this); break; } } //處理事件邏輯 @Subscribe(threadMode = ThreadMode.MAIN, sticky = true) public void receiveEventBus(MessageEvent messageEvent) { mTvReceive.setText(messageEvent.toString()); } @Override protected void onDestroy() { super.onDestroy(); //解注冊 EventBus.getDefault().removeAllStickyEvents(); EventBus.getDefault().unregister(SecActivity.this); } }
-
實(shí)現(xiàn)效果
<p>
-
五、栗子下載
??????源碼鏈接