什么是EventBus
EventBus是Android下高效的發(fā)布/訂閱事件總線機(jī)制助泽。作用是可以代替?zhèn)鹘y(tǒng)的Intent,Handler,Broadcast或接口函數(shù)在Fragment,Activity,Service,線程之間傳遞數(shù)據(jù),執(zhí)行方法装盯,也可以通過(guò)調(diào)用普通類開(kāi)啟發(fā)送消息铆惑。特點(diǎn)是代碼簡(jiǎn)潔畔咧,是一種發(fā)布訂閱設(shè)計(jì)模式(Publish/Subsribe)违诗,或稱作觀察者設(shè)計(jì)模式。
如何使用EventBus
- Publisher是發(fā)布者, 通過(guò)post()方法將消息事件Event發(fā)布到事件總線
- EventBus是事件總線惰瓜, 遍歷所有已經(jīng)注冊(cè)事件的訂閱者們否副,找到里邊的onEvent等4個(gè)方法,分發(fā)Event
- Subscriber是訂閱者崎坊, 收到事件總線發(fā)下來(lái)的消息备禀。即onEvent方法被執(zhí)行。注意參數(shù)類型必須和發(fā)布者發(fā)布的參數(shù)一致奈揍。
MainActivity.java
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
public class MainActivity extends FragmentActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
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:divider="?android:attr/dividerHorizontal"
android:orientation="horizontal"
android:showDividers="middle"
android:baselineAligned="false"
tools:context="com.itheima.eventbusdemo.MainActivity" >
<fragment
android:id="@+id/left_fragment"
android:name="com.itheima.eventbusdemo.LeftFragment"
android:layout_width="0dip"
android:layout_height="match_parent"
android:layout_weight="1" />
<fragment
android:id="@+id/right_fragment"
android:name="com.itheima.eventbusdemo.RightFragment"
android:layout_width="0dip"
android:layout_height="match_parent"
android:layout_weight="3" />
</LinearLayout>
fragment_left.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<Button
android:id="@+id/bt"
android:textSize="14sp"
android:layout_centerInParent="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="按鈕" />
</RelativeLayout>
fragment_right.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<Button
android:id="@+id/bt"
android:textSize="14sp"
android:layout_centerInParent="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="按鈕" />
</RelativeLayout>
LeftFragment.java
import android.os.Bundle;
import android.support.v4.app.ListFragment;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import de.greenrobot.event.EventBus;
public class LeftFragment extends ListFragment {
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
String[] strs = new String[]{"主線程消息1", "子線程消息1", "主線程消息2","通過(guò)普通類發(fā)送消息"};
setListAdapter(new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, strs));
}
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
switch (position) {
case 0:
// 主線程
System.out.println("----------------------主線程發(fā)的消息1"
+ " threadName: "+ Thread.currentThread().getName()
+ " threadId: " + Thread.currentThread().getId());
EventBus.getDefault().post(new MsgEvent1("主線程發(fā)的消息1"));
break;
case 1:
// 子線程
new Thread(){
public void run() {
System.out.println("----------------------子線程發(fā)的消息1"
+ " threadName: "+ Thread.currentThread().getName()
+ " threadId: " + Thread.currentThread().getId());
EventBus.getDefault().post(new MsgEvent1("子線程發(fā)的消息1"));
};
}.start();
break;
case 2:
// 主線程
System.out.println("----------------------主線程發(fā)的消息2"
+ " threadName: "+ Thread.currentThread().getName()
+ " threadId: " + Thread.currentThread().getId());
EventBus.getDefault().post(new MsgEvent2("主線程發(fā)的消息2"));
break;
case 3:
// 子線程2
new Thread(){
public void run() {
System.out.println("----------------------子線程發(fā)的類EventBus1消息1"
+ " threadName: "+ Thread.currentThread().getName()
+ " threadId: " + Thread.currentThread().getId());
new EventBus1();//調(diào)用類EventBus1傳送消息
}
}.start();
}
}
}
RightFragment.java
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import de.greenrobot.event.EventBus;
public class RightFragment extends Fragment {
private TextView tv;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 界面創(chuàng)建時(shí)痹届,訂閱事件, 接受消息
EventBus.getDefault().register(this);
}
@Override
public void onDestroy() {
super.onDestroy();
// 界面銷毀時(shí)打月,取消訂閱
EventBus.getDefault().unregister(this);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_right, null);
tv = (TextView) view.findViewById(R.id.tv);
return view;
}
/**
* 與發(fā)布者在同一個(gè)線程
* @param msg 事件1
*/
public void onEvent(MsgEvent1 msg){
String content = msg.getMsg()
+ "\n ThreadName: " + Thread.currentThread().getName()
+ "\n ThreadId: " + Thread.currentThread().getId()+"\n onEvent";
System.out.println("onEvent(MsgEvent1 msg)收到" + content);
}
/**
* 執(zhí)行在主線程队腐。
* 非常實(shí)用,可以在這里將子線程加載到的數(shù)據(jù)直接設(shè)置到界面中奏篙。
* @param msg 事件1
*/
public void onEventMainThread(MsgEvent1 msg){
String content = msg.getMsg()
+ "\n ThreadName: " + Thread.currentThread().getName()
+ "\n ThreadId: " + Thread.currentThread().getId()+"\n onEventMainThread";
System.out.println("onEventMainThread(MsgEvent1 msg)收到" + content);
tv.setText(content);
}
/**
* 執(zhí)行在子線程柴淘,如果發(fā)布者是子線程則直接執(zhí)行,如果發(fā)布者不是子線程秘通,則創(chuàng)建一個(gè)再執(zhí)行
* 此處可能會(huì)有線程阻塞問(wèn)題为严。
* @param msg 事件1
*/
public void onEventBackgroundThread(MsgEvent1 msg){
String content = msg.getMsg()
+ "\n ThreadName: " + Thread.currentThread().getName()
+ "\n ThreadId: " + Thread.currentThread().getId()+"\n onEventBackgroundThread";
System.out.println("onEventBackgroundThread(MsgEvent1 msg)收到" + content);
}
/**
* 執(zhí)行在在一個(gè)新的子線程
* 適用于多個(gè)線程任務(wù)處理, 內(nèi)部有線程池管理肺稀。
* @param msg 事件1
*/
public void onEventAsync(MsgEvent1 msg){
String content = msg.getMsg()
+ "\n ThreadName: " + Thread.currentThread().getName()
+ "\n ThreadId: " + Thread.currentThread().getId()+"\n onEventAsync";
System.out.println("onEventAsync(MsgEvent1 msg)收到" + content);
}
/**
* 與發(fā)布者在同一個(gè)線程
* @param msg 事件2
*/
public void onEvent(MsgEvent2 msg){
String content = msg.getMsg()
+ "\n ThreadName: " + Thread.currentThread().getName()
+ "\n ThreadId: " + Thread.currentThread().getId()+"\n msg2";
System.out.println("onEvent(MsgEvent2 msg)收到" + content);
tv.setText(content);
}
}
MsgEvent1.java
public class MsgEvent1 {
private String msg;
public MsgEvent1(String msg) {
super();
this.msg = msg;
}
public String getMsg() {
return msg;
}
}
MsgEvent2.java
public class MsgEvent2 {
private String msg;
public MsgEvent2(String msg) {
super();
this.msg = msg;
}
public String getMsg() {
return msg;
}
}
EventBus1.java
import de.greenrobot.event.EventBus;
public class EventBus1 {
public EventBus1() {
// TODO Auto-generated constructor stub
EventBus.getDefault().post(new MsgEvent1("類EventBus1發(fā)的消息1"));
}
}
效果圖:
源碼地址:https://git.oschina.net/Fly321/EventBus.git
EventBus的ThreadMode
EventBus包含4個(gè)ThreadMode:PostThread第股,MainThread,BackgroundThread话原,Async
MainThread我們已經(jīng)不陌生了夕吻;我們已經(jīng)使用過(guò)。
具體的用法繁仁,極其簡(jiǎn)單涉馅,方法名為:onEventPostThread, onEventMainThread黄虱,onEventBackgroundThread稚矿,onEventAsync即可
具體什么區(qū)別呢?
- onEventMainThread代表這個(gè)方法會(huì)在UI線程執(zhí)行
- onEventPostThread代表這個(gè)方法會(huì)在當(dāng)前發(fā)布事件的線程執(zhí)行
- BackgroundThread這個(gè)方法捻浦,如果在非UI線程發(fā)布的事件晤揣,則直接執(zhí)行,和發(fā)布在同一個(gè)線程中朱灿。如果在UI線程發(fā)布的事件昧识,則加入后臺(tái)任務(wù)隊(duì)列,使用線程池一個(gè)接一個(gè)調(diào)用母剥。
Async 加入后臺(tái)任務(wù)隊(duì)列滞诺,使用線程池調(diào)用形导,注意沒(méi)有BackgroundThread中的一個(gè)接一個(gè)环疼。