Android中EventBus的使用

什么是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

EventBus.png
  1. Publisher是發(fā)布者, 通過(guò)post()方法將消息事件Event發(fā)布到事件總線
  2. EventBus是事件總線惰瓜, 遍歷所有已經(jīng)注冊(cè)事件的訂閱者們否副,找到里邊的onEvent等4個(gè)方法,分發(fā)Event
  3. 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"));
    }
}
效果圖:
效果圖.gif

源碼地址: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è)环疼。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末习霹,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子炫隶,更是在濱河造成了極大的恐慌淋叶,老刑警劉巖,帶你破解...
    沈念sama閱讀 210,978評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件伪阶,死亡現(xiàn)場(chǎng)離奇詭異煞檩,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)栅贴,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門斟湃,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人檐薯,你說(shuō)我怎么就攤上這事凝赛。” “怎么了坛缕?”我有些...
    開(kāi)封第一講書人閱讀 156,623評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵墓猎,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我赚楚,道長(zhǎng)毙沾,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 56,324評(píng)論 1 282
  • 正文 為了忘掉前任宠页,我火速辦了婚禮左胞,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘举户。我一直安慰自己罩句,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,390評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布敛摘。 她就那樣靜靜地躺著门烂,像睡著了一般。 火紅的嫁衣襯著肌膚如雪兄淫。 梳的紋絲不亂的頭發(fā)上屯远,一...
    開(kāi)封第一講書人閱讀 49,741評(píng)論 1 289
  • 那天,我揣著相機(jī)與錄音捕虽,去河邊找鬼慨丐。 笑死,一個(gè)胖子當(dāng)著我的面吹牛泄私,可吹牛的內(nèi)容都是我干的房揭。 我是一名探鬼主播备闲,決...
    沈念sama閱讀 38,892評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼捅暴!你這毒婦竟也來(lái)了恬砂?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 37,655評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤蓬痒,失蹤者是張志新(化名)和其女友劉穎泻骤,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體梧奢,經(jīng)...
    沈念sama閱讀 44,104評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡狱掂,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了亲轨。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片趋惨。...
    茶點(diǎn)故事閱讀 38,569評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖惦蚊,靈堂內(nèi)的尸體忽然破棺而出器虾,到底是詐尸還是另有隱情,我是刑警寧澤养筒,帶...
    沈念sama閱讀 34,254評(píng)論 4 328
  • 正文 年R本政府宣布曾撤,位于F島的核電站,受9級(jí)特大地震影響晕粪,放射性物質(zhì)發(fā)生泄漏挤悉。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,834評(píng)論 3 312
  • 文/蒙蒙 一巫湘、第九天 我趴在偏房一處隱蔽的房頂上張望装悲。 院中可真熱鬧,春花似錦尚氛、人聲如沸诀诊。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,725評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)属瓣。三九已至,卻和暖如春讯柔,著一層夾襖步出監(jiān)牢的瞬間抡蛙,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,950評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工魂迄, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留粗截,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,260評(píng)論 2 360
  • 正文 我出身青樓捣炬,卻偏偏與公主長(zhǎng)得像熊昌,于是被迫代替她去往敵國(guó)和親绽榛。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,446評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容

  • 最近在項(xiàng)目中使用了EventBus(3.0)婿屹,覺(jué)得非常好用灭美,于是就看了一些關(guān)于EventBus源碼分析的文章,現(xiàn)在...
    shenhuniurou閱讀 1,494評(píng)論 0 4
  • 一选泻、簡(jiǎn)介 EventBus是由greenrobot 組織貢獻(xiàn)的一個(gè)Android事件發(fā)布/訂閱輕量級(jí)框架冲粤。Even...
    Mr丶sorrow閱讀 14,975評(píng)論 0 13
  • 先吐槽一下博客園的MarkDown編輯器美莫,推出的時(shí)候還很高興博客園支持MarkDown了页眯,試用了下發(fā)現(xiàn)支持不完善就...
    Ten_Minutes閱讀 559評(píng)論 0 2
  • Android 淺析EventBus (一) 使用 前言 Linus Benedict Torvalds : RT...
    CodePlayer_Jz閱讀 3,104評(píng)論 3 10
  • 魚,我所欲也厢呵,熊掌窝撵,亦我所欲也,二者不可兼得襟铭,舍魚而取熊掌者也碌奉。生,亦我所欲也寒砖,義赐劣,亦我所欲也,二者不可兼得哩都,舍生...
    識(shí)學(xué)閱讀 427評(píng)論 0 0