一、概述
EventBus是一款針對Android優(yōu)化的發(fā)布/訂閱事件總線。主要功能是替代Intent,Handler,BroadCast在Fragment,Activity,Service汗唱,線程之間傳遞消息.優(yōu)點是開銷小,代碼更優(yōu)雅缀雳。以及將發(fā)送者和接收者解耦渡嚣。
其他參閱網(wǎng)址:http://www.reibang.com/p/da9e193e8b03
EventBus 利弊與源碼解析
1梢睛、下載EventBus的類庫
源碼:https://github.com/greenrobot/EventBus
2肥印、基本使用
(1)自定義一個類,可以是空類绝葡,比如:
public class AnyEventType {
public AnyEventType(){}
}
(2)在要接收消息的頁面注冊:
eventBus.register(this);
(3)發(fā)送消息
eventBus.post(new AnyEventType event);
(4)接受消息的頁面實現(xiàn)(共有四個函數(shù)深碱,各功能不同,這是其中之一藏畅,可以選擇性的實現(xiàn)敷硅,這里先實現(xiàn)一個):
public void onEvent(AnyEventType event) {}
(5)解除注冊
eventBus.unregister(this);
順序就是這么個順序功咒,可真正讓自己寫,估計還是云里霧里的绞蹦,下面舉個例子來說明下力奋。
首先,在EventBus中幽七,獲取實例的方法一般是采用EventBus.getInstance()來獲取默認的EventBus實例景殷,當然你也可以new一個又一個,個人感覺還是用默認的比較好澡屡,以防出錯猿挚。
二、實戰(zhàn)
先給大家看個例子:
當擊btn_try按鈕的時候驶鹉,跳到第二個Activity绩蜻,當點擊第二個activity上面的First Event按鈕的時候向第一個Activity發(fā)送消息,當?shù)谝粋€Activity收到消息后室埋,一方面將消息Toast顯示办绝,一方面放入textView中顯示。
按照下面的步驟词顾,下面來建這個工程:
1八秃、基本框架搭建
想必大家從一個Activity跳轉(zhuǎn)到第二個Activity的程序應該都會寫,這里先稍稍把兩個Activity跳轉(zhuǎn)的代碼建起來肉盹。后面再添加EventBus相關(guān)的玩意昔驱。
MainActivity布局(activity_main.xml)
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:id="@+id/btn_try"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="btn_bty"/>
<TextView
android:id="@+id/tv"
android:layout_width="wrap_content"
android:layout_height="match_parent"/>
</LinearLayout>
新建一個Activity,SecondActivity布局(activity_second.xml)
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.harvic.try_eventbus_1.SecondActivity" >
<Button
android:id="@+id/btn_first_event"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="First Event"/>
</LinearLayout>
MainActivity.java (點擊btn跳轉(zhuǎn)到第二個Activity)
public class MainActivity extends Activity {
Button btn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn = (Button) findViewById(R.id.btn_try);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Intent intent = new Intent(getApplicationContext(),
SecondActivity.class);
startActivity(intent);
}
});
}
}
到這上忍,基本框架就搭完了骤肛,下面開始按步驟使用EventBus了。
2窍蓝、新建一個類FirstEvent
package com.harvic.other;
public class FirstEvent {
private String mMsg;
public FirstEvent(String msg) {
// TODO Auto-generated constructor stub
mMsg = msg;
}
public String getMsg(){
return mMsg;
}
}
這個類很簡單腋颠,構(gòu)造時傳進去一個字符串,然后可以通過getMsg()獲取出來吓笙。
3淑玫、在要接收消息的頁面注冊EventBus:
在上面的GIF圖片的演示中,大家也可以看到面睛,我們是要在MainActivity中接收發(fā)過來的消息的絮蒿,所以我們在MainActivity中注冊消息。
通過我們會在OnCreate()函數(shù)中注冊EventBus叁鉴,在OnDestroy()函數(shù)中反注冊土涝。所以整體的注冊與反注冊的代碼如下:
import com.harvic.other.FirstEvent;
import de.greenrobot.event.EventBus;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends Activity {
Button btn;
TextView tv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//注冊EventBus
EventBus.getDefault().register(this);
btn = (Button) findViewById(R.id.btn_try);
tv = (TextView)findViewById(R.id.tv);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Intent intent = new Intent(getApplicationContext(),
SecondActivity.class);
startActivity(intent);
}
});
}
@Override
protected void onDestroy(){
super.onDestroy();
EventBus.getDefault().unregister(this);//反注冊EventBus
}
}
4、發(fā)送消息
發(fā)送消息是使用EventBus中的Post方法來實現(xiàn)發(fā)送的幌墓,發(fā)送過去的是我們新建的類的實例但壮!
EventBus.getDefault().post(new FirstEvent("FirstEvent btn clicked"));
完整的SecondActivity.java的代碼如下:
import com.harvic.other.FirstEvent;
import de.greenrobot.event.EventBus;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class SecondActivity extends Activity {
private Button btn_FirstEvent;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
btn_FirstEvent = (Button) findViewById(R.id.btn_first_event);
btn_FirstEvent.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
EventBus.getDefault().post(
new FirstEvent("FirstEvent btn clicked"));
}
});
}
}
5冀泻、接收消息
接收消息時,我們使用EventBus中最常用的onEventMainThread()函數(shù)來接收消息蜡饵,具體為什么用這個弹渔,我們下篇再講,這里先給大家一個初步認識溯祸,要先能把EventBus用起來先捞附。
在MainActivity中重寫onEventMainThread(FirstEvent event),參數(shù)就是我們自己定義的類:
在收到Event實例后您没,我們將其中攜帶的消息取出鸟召,一方面Toast出去,一方面?zhèn)鞯絋extView中氨鹏;
public void onEventMainThread(FirstEvent event) {
String msg = "onEventMainThread收到了消息:" + event.getMsg();
Log.d("harvic", msg);
tv.setText(msg);
Toast.makeText(this, msg, Toast.LENGTH_LONG).show();
}
完整的MainActiviy代碼如下:
import com.harvic.other.FirstEvent;
import de.greenrobot.event.EventBus;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends Activity {
Button btn;
TextView tv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
EventBus.getDefault().register(this);
btn = (Button) findViewById(R.id.btn_try);
tv = (TextView)findViewById(R.id.tv);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Intent intent = new Intent(getApplicationContext(),
SecondActivity.class);
startActivity(intent);
}
});
}
public void onEventMainThread(FirstEvent event) {
String msg = "onEventMainThread收到了消息:" + event.getMsg();
Log.d("harvic", msg);
tv.setText(msg);
Toast.makeText(this, msg, Toast.LENGTH_LONG).show();
}
@Override
protected void onDestroy(){
super.onDestroy();
EventBus.getDefault().unregister(this);
}
}
好了欧募,到這,基本上算初步把EventBus用起來了仆抵,下篇再講講EventBus的幾個函數(shù)跟继,及各個函數(shù)間是如何識別當前如何調(diào)用哪個函數(shù)的。
6镣丑、補充
前一篇給大家裝簡單演示了EventBus的onEventMainThread()函數(shù)的接收舔糖,其實EventBus還有另外有個不同的函數(shù),他們分別是:
1莺匠、onEvent2金吗、onEventMainThread3、onEventBackgroundThread4趣竣、onEventAsync
這四種訂閱函數(shù)都是使用onEvent開頭的摇庙,它們的功能稍有不同,在介紹不同之前先介紹兩個概念:告知觀察者事件發(fā)生時通過EventBus.post函數(shù)實現(xiàn),這個過程叫做事件的發(fā)布遥缕,觀察者被告知事件發(fā)生叫做事件的接收卫袒,是通過下面的訂閱函數(shù)實現(xiàn)的。onEvent:如果使用onEvent作為訂閱函數(shù)单匣,那么該事件在哪個線程發(fā)布出來的,onEvent就會在這個線程中運行户秤,也就是說發(fā)布事件和接收事件線程在同一個線程码秉。使用這個方法時,在onEvent方法中不能執(zhí)行耗時操作虎忌,如果執(zhí)行耗時操作容易導致事件分發(fā)延遲泡徙。onEventMainThread****:如果使用onEventMainThread作為訂閱函數(shù)橱鹏,那么不論事件是在哪個線程中發(fā)布出來的膜蠢,onEventMainThread都會在UI線程中執(zhí)行堪藐,接收事件就會在UI線程中運行,這個在Android中是非常有用的挑围,因為在Android中只能在UI線程中跟新UI礁竞,所以在onEvnetMainThread方法中是不能執(zhí)行耗時操作的。onEventBackground:如果使用onEventBackgrond作為訂閱函數(shù)杉辙,那么如果事件是在UI線程中發(fā)布出來的模捂,那么onEventBackground就會在子線程中運行,如果事件本來就是子線程中發(fā)布出來的蜘矢,那么onEventBackground函數(shù)直接在該子線程中執(zhí)行狂男。onEventAsync:使用這個函數(shù)作為訂閱函數(shù),那么無論事件在哪個線程發(fā)布品腹,都會創(chuàng)建新的子線程在執(zhí)行onEventAsync.
二岖食、實戰(zhàn)
1、解析
上面列出的這四個函數(shù)舞吭,關(guān)鍵問題在于泡垃,我們怎么指定調(diào)用哪個函數(shù)呢?
我們先研究一下羡鸥,上一篇中是怎么調(diào)用的onEventMainThread函數(shù)蔑穴,除了在接收端注冊與反注冊以后,關(guān)鍵問題在于新建的一個類:
新建一個類:
package com.harvic.other;
public class FirstEvent {
private String mMsg;
public FirstEvent(String msg) {
// TODO Auto-generated constructor stub
mMsg = msg;
}
public String getMsg(){
return mMsg;
}
}
發(fā)送時:
EventBus.getDefault().post(new FirstEvent("FirstEvent btn clicked"));
接收時:
public void onEventMainThread(FirstEvent event) {
……
}
發(fā)現(xiàn)什么問題了沒惧浴?
沒錯存和,發(fā)送時發(fā)送的是這個類的實例,接收時參數(shù)就是這個類實例衷旅。
所以Q埔Α!N咭稹P鹆俊!九串!當發(fā)過來一個消息的時候绞佩,EventBus怎么知道要調(diào)哪個函數(shù)呢,就看哪個函數(shù)傳進去的參數(shù)是這個類的實例猪钮,哪個是就調(diào)哪個品山。那如果有兩個是呢,那兩個都會被調(diào)用?镜汀V饨弧!扑馁!
為了證明這個問題涯呻,下面寫個例子凉驻,先看下效果
2、實例
先看看我們要實現(xiàn)的效果:
這次我們在上一篇的基礎(chǔ)上复罐,新建三個類:FirstEvent涝登、SecondEvent、ThirdEvent,在第二個Activity中發(fā)送請求效诅,在MainActivity中接收這三個類的實例胀滚,接收時的代碼為:
public void onEventMainThread(FirstEvent event) {
Log.d("harvic", "onEventMainThread收到了消息:" + event.getMsg());
}
public void onEventMainThread(SecondEvent event) {
Log.d("harvic", "onEventMainThread收到了消息:" + event.getMsg());
}
public void onEvent(ThirdEvent event) {
Log.d("harvic", "OnEvent收到了消息:" + event.getMsg());
}
使用兩個onEventMainThread分別接收FirstEvent實例的消息和SecondEvent實例的消息,使用onEvent接收ThirdEvent實例的消息乱投。界面操作及結(jié)果如下:
Log輸出結(jié)果:
可以看到咽笼,在發(fā)送FirstEvent時,在MainActiviy中雖然有三個函數(shù)戚炫,但只有第一個onEventMainThread函數(shù)的接收參數(shù)是FirstEvent褐荷,所以會傳到它這來接收。所以這里識別調(diào)用EventBus中四個函數(shù)中哪個函數(shù)嘹悼,是通過參數(shù)中的實例來決定的叛甫。
因為我們是在上一篇例子的基礎(chǔ)上完成的,所以這里的代碼就不詳細寫了杨伙,只寫改動的部分其监。
1、三個類
a:
public class FirstEvent {
private String mMsg;
public FirstEvent(String msg) {
// TODO Auto-generated constructor stub
mMsg = msg;
}
public String getMsg(){
return mMsg;
}
}
b:
public class SecondEvent{
private String mMsg;
public SecondEvent(String msg) {
// TODO Auto-generated constructor stub
mMsg = "MainEvent:"+msg;
}
public String getMsg(){
return mMsg;
}
}
c:
public class ThirdEvent {
private String mMsg;
public ThirdEvent(String msg) {
// TODO Auto-generated constructor stub
mMsg = msg;
}
public String getMsg(){
return mMsg;
}
}
2限匣、發(fā)送
然后在SecondActivity中新建三個按鈕抖苦,分別發(fā)送不同的類的實例,代碼如下:
import com.harvic.other.FirstEvent;
import com.harvic.other.SecondEvent;
import com.harvic.other.ThirdEvent;
import de.greenrobot.event.EventBus;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class SecondActivity extends Activity {
private Button btn_FirstEvent, btn_SecondEvent, btn_ThirdEvent;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
btn_FirstEvent = (Button) findViewById(R.id.btn_first_event);
btn_SecondEvent = (Button) findViewById(R.id.btn_second_event);
btn_ThirdEvent = (Button) findViewById(R.id.btn_third_event);
btn_FirstEvent.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
EventBus.getDefault().post(
new FirstEvent("FirstEvent btn clicked"));
}
});
btn_SecondEvent.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
EventBus.getDefault().post(
new SecondEvent("SecondEvent btn clicked"));
}
});
btn_ThirdEvent.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
EventBus.getDefault().post(
new ThirdEvent("ThirdEvent btn clicked"));
}
});
}
}
3米死、接收
在MainActivity中锌历,除了注冊與注冊,我們利用onEventMainThread(FirstEvent event)來接收來自FirstEvent的消息峦筒,使用onEventMainThread(SecondEvent event)接收來自SecondEvent 實例的消息究西,使用onEvent(ThirdEvent event) 來接收ThirdEvent 實例的消息。
package com.harvic.tryeventbus2;
import com.harvic.other.FirstEvent;
import com.harvic.other.SecondEvent;
import com.harvic.other.ThirdEvent;
import de.greenrobot.event.EventBus;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends Activity {
Button btn;
TextView tv;
EventBus eventBus;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
EventBus.getDefault().register(this);
btn = (Button) findViewById(R.id.btn_try);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Intent intent = new Intent(getApplicationContext(),
SecondActivity.class);
startActivity(intent);
}
});
}
public void onEventMainThread(FirstEvent event) {
Log.d("harvic", "onEventMainThread收到了消息:" + event.getMsg());
}
public void onEventMainThread(SecondEvent event) {
Log.d("harvic", "onEventMainThread收到了消息:" + event.getMsg());
}
public void onEvent(ThirdEvent event) {
Log.d("harvic", "OnEvent收到了消息:" + event.getMsg());
}
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
EventBus.getDefault().unregister(this);
}
}
到這里物喷,代碼就結(jié)束 了卤材,從上面的代碼,我們可以看到峦失,EventBus是怎么接收消息的扇丛,是根據(jù)參數(shù)中類的實例的類型的判定的,所以當如果我們在接收時尉辑,同一個類的實例參數(shù)有兩個函數(shù)來接收會怎樣帆精?答案是,這兩個函數(shù)都會執(zhí)行,下面實驗一下:
在MainActivity中接收時卓练,我們在接收SecondEvent時隘蝎,在上面onEventMainThread基礎(chǔ)上另加一個onEventBackgroundThread和onEventAsync,即下面的代碼:
//SecondEvent接收函數(shù)一
public void onEventMainThread(SecondEvent event) {
Log.d("harvic", "onEventMainThread收到了消息:" + event.getMsg());
}
//SecondEvent接收函數(shù)二
public void onEventBackgroundThread(SecondEvent event){
Log.d("harvic", "onEventBackground收到了消息:" + event.getMsg());
}
//SecondEvent接收函數(shù)三
public void onEventAsync(SecondEvent event){
Log.d("harvic", "onEventAsync收到了消息:" + event.getMsg());
}
完整的代碼在這里:
import com.harvic.other.FirstEvent;
import com.harvic.other.SecondEvent;
import com.harvic.other.ThirdEvent;
import de.greenrobot.event.EventBus;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends Activity {
Button btn;
TextView tv;
EventBus eventBus;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
EventBus.getDefault().register(this);
btn = (Button) findViewById(R.id.btn_try);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Intent intent = new Intent(getApplicationContext(),
SecondActivity.class);
startActivity(intent);
}
});
}
public void onEventMainThread(FirstEvent event) {
Log.d("harvic", "onEventMainThread收到了消息:" + event.getMsg());
}
//SecondEvent接收函數(shù)一
public void onEventMainThread(SecondEvent event) {
Log.d("harvic", "onEventMainThread收到了消息:" + event.getMsg());
}
//SecondEvent接收函數(shù)二
public void onEventBackgroundThread(SecondEvent event){
Log.d("harvic", "onEventBackground收到了消息:" + event.getMsg());
}
//SecondEvent接收函數(shù)三
public void onEventAsync(SecondEvent event){
Log.d("harvic", "onEventAsync收到了消息:" + event.getMsg());
}
public void onEvent(ThirdEvent event) {
Log.d("harvic", "OnEvent收到了消息:" + event.getMsg());
}
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
EventBus.getDefault().unregister(this);
}
}
經(jīng)過上面的分析昆庇,當發(fā)送SecondEvent實例的消息過來的時候,這三個函數(shù)會同時接收到并各自執(zhí)行闸溃,所以當點擊Second Event這個button的時候整吆,會出現(xiàn)下面的結(jié)果:
好啦,這篇就到了辉川,講來講去就是說一個問題:消息的接收是根據(jù)參數(shù)中的類名來決定執(zhí)行哪一個的表蝙;
源碼地址:http://download.csdn.net/detail/harvic880925/8111357
參考:**http://blog.csdn.net/harvic880925/article/details/40660137 **