EventBus使用之基礎

jopen 8年前發布 | 8K 次閱讀 Android開發 移動開發

PS一句:最終還是選擇CSDN來整理發表這幾年的知識點,該文章平行遷移到CSDN。因為CSDN也支持MarkDown語法了,牛逼啊!

【工匠若水 http://blog.csdn.net/yanbober

開源項目鏈接

EventBus項目:https://github.com/greenrobot/EventBus
EventBusDemo下載:https://github.com/yanbober/Android-Blog-Source/tree/master/Android-EventBus-Demo

背景介紹

如果你學習過設計模式,那么當想通知其他組件某些事情發生時你一定會使用觀察者模式。好了,既然能想到這個設計模式,那么就來看一個屌爆天的Android開源框架EventBus。主要功能是替代Intent、Handler、BroadCast在Fragment、Activity、Service、線程之間傳遞消息。他的最牛逼優點是開銷小,代碼簡潔,解耦代碼。

基礎介紹

上面說了,EventBus是一個觀察者模式的實現,既然這樣,那他就有如下三個要素:

  • Event:事件
  • Subscriber:事件訂閱者,接收特定的事件。
  • Publisher:事件發布者,用于通知Subscriber有事件發生。

其中,Event可以使任意類型對象。Subscriber都是以約定的onEvent開頭的函數,具體是onEvent,onEventMainThread,onEventBackgroundThread,onEventAsync這四個。Publisher可以通過post(Object)在任意線程任意位置發送事件。

官方這個圖就很直觀的說明了這種觀察者模式的架構:

這里寫圖片描述

依據開源庫組件的說明文檔來操作:

  1. 在工程gradle中添加:compile ‘de.greenrobot:eventbus:2.4.0’。
  2. 按照文檔HOWTO.md進行操作。

Subscriber以onEvent開頭的4個函數區別:

  • onEvent:事件的處理在和事件的發送在相同的線程,所以事件處理時間不應太長,不然影響事件的發送線程。

  • onEventMainThread: 事件的處理會在UI線程中執行。事件處理時間不能太長,長了會出現臭名遠之的ANR。

  • onEventBackgroundThread:事件的處理會在一個后臺線程中執行。雖然名字是BackgroundThread,事件處理是在后臺線程,但事件處理時間還是不應該太長,因為如果發送事件的線程是后臺線程,會直接在當前后臺線程執行事件;如果當前線程是UI線程,事件會被加到一個隊列中,由一個線程依次處理這些事件,如果某個事件處理時間太長,會阻塞后面的事件的派發或處理。

  • onEventAsync:事件處理會在單獨的線程中執行,主要用于在后臺線程中執行耗時操作,每個事件會開啟一個線程,但最好限制線程的數目。

下面還是先上代碼再總結分析。

實戰一把屌爆天的功能

如下示例演示了EventBus的線程間通信與線程內通信及自定義消息結構的通信。

下載該實例工程完整代碼點擊我

如下是主界面顯示效果:

這里寫圖片描述

接著看代碼:

首先自定義一個消息數據類型,如下:

public class MsgBean {
    private String msg;

    public MsgBean(String msg) {
        this.msg = msg;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }
}

接著編寫主界面及邏輯代碼:

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private TextView mShowInfo1, mShowInfo2, mShowInfo21, mShowInfo22;
    private Button mBtn1, mBtn2, mBtn21, mBtn22;

    private int mCount = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initData();
    }

    private void initData() {
        mShowInfo1 = (TextView) findViewById(R.id.first_show);
        mBtn1 = (Button) findViewById(R.id.get_btn_1);
        mBtn1.setOnClickListener(this);

        mShowInfo2 = (TextView) findViewById(R.id.second_show);
        mBtn2 = (Button) findViewById(R.id.get_btn_2);
        mBtn2.setOnClickListener(this);

        mShowInfo21 = (TextView) findViewById(R.id.first_show_lin2);
        mBtn21 = (Button) findViewById(R.id.get_btn_1_line2);
        mBtn21.setOnClickListener(this);

        mShowInfo22 = (TextView) findViewById(R.id.second_show_line2);
        mBtn22 = (Button) findViewById(R.id.get_btn_2_line2);
        mBtn22.setOnClickListener(this);
    }

    @Override
    protected void onStart() {
        super.onStart();
        //注冊EventBus
        EventBus.getDefault().register(this);
    }

    @Override
    protected void onStop() {
        super.onStop();
        //取消EventBus
        EventBus.getDefault().unregister(this);
    }

    //事件1接收者:在主線程接收
    public void onEvent(String event){
        mShowInfo1.setText(event);
    }
    //事件2接收者:在主線程接收自定義MsgBean消息
    public void onEvent(MsgBean event){
        mShowInfo21.setText(event.getMsg());
    }
    //事件3接收者:在主線程接收
    public void onEventMainThread(Integer event) {
        mShowInfo2.setText(event+"");
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.get_btn_1:
                //事件1發送者:在主線程發送
                EventBus.getDefault().post("test!");
                break;
            case R.id.get_btn_1_line2:
                //事件2發送者:在主線程發送自定義MsgBean消息
                EventBus.getDefault().post(new MsgBean("type"));
                break;
            case R.id.get_btn_2:
                //事件3發送者:在子線程循環發送
                new Timer().schedule(new TimerTask() {
                    @Override
                    public void run() {
                        EventBus.getDefault().post(mCount);
                        if (mCount >= 3) {
                            this.cancel();
                            mCount = 0;
                        }
                        mCount++;
                    }
                }, 0, 1000);
                break;
        }
    }
}

xml代碼太簡單就省略了。

如下運行結果:

這里寫圖片描述

下載該實例工程完整代碼點擊我

從上面代碼可以看見,當發過來一個消息的時候,EventBus區分onEventxxx被調運通過發送消息的參數類型區分(如:post(new MsgBean(“type”))對應onEvent(MsgBean event),post(“test!”)對應onEvent(String event))。

總結

通過上面基礎實戰發現,使用EventBus的基本步驟就是如下4步:

  1. 定義事件類型(或者不定義)。例如:MsgBean等
  2. 定義事件處理方法。例如:onEvent等
  3. 注冊訂閱者。例如:EventBus.getDefault().register(this)
  4. 發送事件。例如:EventBus.getDefault().post(new MyEvent())

通過這個例子基本上你就可以上手EventBus框架使用了,也知道了大致基本原理。其實這還是不夠,玩意出現bug又很郁悶不知道怎么改,所以下一篇還是老規矩,走讀一下EventBus的大致源碼,學習下作者的代碼思想,同時熟悉EventBus的原理。

【工匠若水 http://blog.csdn.net/yanbober
繼續閱讀本系列下一篇《EventBus框架庫代碼走讀》

來自: http://blog.csdn.net//yanbober/article/details/45667363

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!