EventBus的使用和原理在網(wǎng)上有很多的博客了,其中泓洋大哥啟艦寫的非常非常棒,我也是跟著他們的博客學(xué)會的EventBus,因為是第一次接觸并使用EventBus,所以我寫的更多是如何使用,源碼解析就不怎么樣啦!

如需轉(zhuǎn)載請注明出處:Android EventBus 3.0 實例使用詳解

電腦培訓(xùn),計算機培訓(xùn),平面設(shè)計培訓(xùn),網(wǎng)頁設(shè)計培訓(xùn),美工培訓(xùn),Web培訓(xùn),Web前端開發(fā)培訓(xùn)

一、概述

EventBus是一款A(yù)ndroid下的發(fā)布/訂閱事件總線機制。可以代替Intent、Handler、Broadcast等在Fragment、Activity之間傳遞消息。

優(yōu)點:開銷小,代碼優(yōu)雅。將發(fā)送者和接受者解耦。

既然是有關(guān)于事件的發(fā)布和訂閱,那么發(fā)布者和訂閱者的關(guān)系又是怎樣的呢?

事件的發(fā)布者可以發(fā)布多個事件,發(fā)布者同時也可以是訂閱者,訂閱者可以訂閱多個事件。

二、實例

接下來要通過實例來講解如何使用EventBus了,在看代碼之前要記得三個問題。

1、事件發(fā)布者如何發(fā)布事件

2、事件訂閱者如何訂閱事件

3、訂閱者如何準(zhǔn)確接收發(fā)布者發(fā)布的多個事件中的一個(假設(shè)發(fā)布者發(fā)布多個事件,訂閱者只是訂閱其中的一個事件)

(1)首先在gradle文件中添加EventBus的依賴

compile 'org.greenrobot:eventbus:3.0.0'

(2)在相關(guān)Activity中的onCreat()、onDestory()注冊和解注EventBus

電腦培訓(xùn),計算機培訓(xùn),平面設(shè)計培訓(xùn),網(wǎng)頁設(shè)計培訓(xùn),美工培訓(xùn),Web培訓(xùn),Web前端開發(fā)培訓(xùn)

@Override    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        EventBus.getDefault().register(this);
    }

@Override    protected void onDestroy() {
        super.onDestroy();
        EventBus.getDefault().unregister(this);
    }

電腦培訓(xùn),計算機培訓(xùn),平面設(shè)計培訓(xùn),網(wǎng)頁設(shè)計培訓(xùn),美工培訓(xùn),Web培訓(xùn),Web前端開發(fā)培訓(xùn)

(3)事件發(fā)布者如何發(fā)布事件

EventBus.getDefault().post(實參);

我們到.getDefault()來看一個這個方法:

電腦培訓(xùn),計算機培訓(xùn),平面設(shè)計培訓(xùn),網(wǎng)頁設(shè)計培訓(xùn),美工培訓(xùn),Web培訓(xùn),Web前端開發(fā)培訓(xùn)

/** Convenience singleton for apps using a process-wide EventBus instance. */
    public static EventBus getDefault() {        if (defaultInstance == null) {
            synchronized (EventBus.class) {                if (defaultInstance == null) {
                    defaultInstance = new EventBus();
                }
            }
        }        return defaultInstance;
    }

電腦培訓(xùn),計算機培訓(xùn),平面設(shè)計培訓(xùn),網(wǎng)頁設(shè)計培訓(xùn),美工培訓(xùn),Web培訓(xùn),Web前端開發(fā)培訓(xùn)

這里的.getDefault()方法其實就是一個單例,獲取到EventBus實例后調(diào)用post方法開始發(fā)布事件

post():

電腦培訓(xùn),計算機培訓(xùn),平面設(shè)計培訓(xùn),網(wǎng)頁設(shè)計培訓(xùn),美工培訓(xùn),Web培訓(xùn),Web前端開發(fā)培訓(xùn)

/** Posts the given event to the event bus. */
    public void post(Object event) {
        PostingThreadState postingState = currentPostingThreadState.get();
        List<Object> eventQueue = postingState.eventQueue;
        eventQueue.add(event);        if (!postingState.isPosting) {
            postingState.isMainThread = Looper.getMainLooper() == Looper.myLooper();
            postingState.isPosting = true;            if (postingState.canceled) {                throw new EventBusException("Internal error. Abort state was not reset");
            }            try {                while (!eventQueue.isEmpty()) {
                    postSingleEvent(eventQueue.remove(0), postingState);
                }
            } finally {
                postingState.isPosting = false;
                postingState.isMainThread = false;
            }
        }
    }

電腦培訓(xùn),計算機培訓(xùn),平面設(shè)計培訓(xùn),網(wǎng)頁設(shè)計培訓(xùn),美工培訓(xùn),Web培訓(xùn),Web前端開發(fā)培訓(xùn)

通過源碼可以看得出來,方法的實參是一個對象類型的參數(shù),參數(shù)會統(tǒng)一存儲在eventQueue這個隊列中,然后循環(huán)隊列,將隊列中的消息逐一發(fā)布,這里大家可能會想,每次post都會去調(diào)用整個隊列么,那么不會造成方法多次調(diào)用么?

答案是不會的,因為在最外層加了一個判斷,判斷event是否被發(fā)不過,如果被發(fā)布過,則不會進(jìn)入到這個方法內(nèi)。

(4)事件訂閱者訂閱事件

@Subscribe    public void onEventMainThread(實參){        //接收到發(fā)布者發(fā)布的事件后,進(jìn)行相應(yīng)的處理操作
    }

這里要注意的是:EventBus在 3.0 版本后,事件訂閱監(jiān)聽的方法名可以隨意起,不同于舊版本,名字是特定的。

電腦培訓(xùn),計算機培訓(xùn),平面設(shè)計培訓(xùn),網(wǎng)頁設(shè)計培訓(xùn),美工培訓(xùn),Web培訓(xùn),Web前端開發(fā)培訓(xùn)

public void onEventMainThread(param)  
    {  
    //如果使用onEventMainThread作為訂閱函數(shù),那么不論事件是在哪個線程中發(fā)布出來的,onEventMainThread都會在UI線程中執(zhí)行,接收事件就會在UI線程中運行,
   //這個在Android中是非常有用的,因為在Android中只能在UI線程中跟新UI,所以在onEvnetMainThread方法中是不能執(zhí)行耗時操作的。
   }            
public void onEventPostThread(param)      {       //如果使用onEvent作為訂閱函數(shù),那么該事件在哪個線程發(fā)布出來的,onEvent就會在這個線程中運行,也就是說發(fā)布事件和接收事件線程在同一個線程。
    //使用這個方法時,在onEvent方法中不能執(zhí)行耗時操作,如果執(zhí)行耗時操作容易導(dǎo)致事件分發(fā)延遲。
       }            
public void onEventBackgroundThread(param)      {       //如果使用onEventBackgrond作為訂閱函數(shù),那么如果事件是在UI線程中發(fā)布出來的,那么onEventBackground就會在子線程中運行,如果事件本來就是子線程中發(fā)布出來的,那么onEventBackground函數(shù)直接在該子線程中執(zhí)行。        }            public void onEventAsync(param)      {     //使用這個函數(shù)作為訂閱函數(shù),那么無論事件在哪個線程發(fā)布,都會創(chuàng)建新的子線程在執(zhí)行onEventAsync.            }

電腦培訓(xùn),計算機培訓(xùn),平面設(shè)計培訓(xùn),網(wǎng)頁設(shè)計培訓(xùn),美工培訓(xùn),Web培訓(xùn),Web前端開發(fā)培訓(xùn)

但是新版本需要手動的添加注解@Subscribe(這是必不可少的)。既然名字可以隨意起,那么又怎么控制在什么線程內(nèi)進(jìn)行處理呢?

@Subscribe(threadMode = ThreadMode.MAIN)

給注解設(shè)置ThreadMode就可以了。

(5)事件發(fā)布者和訂閱者如何對應(yīng)上

可以看到發(fā)布事件和訂閱事件,都需要傳入一個實參,而且在post方法中我們也看到了,這個實參是對象類型的,大家猜想的話也可以知道,發(fā)布和訂閱事件是通過一個對象實參來進(jìn)行關(guān)聯(lián)的。

電腦培訓(xùn),計算機培訓(xùn),平面設(shè)計培訓(xùn),網(wǎng)頁設(shè)計培訓(xùn),美工培訓(xùn),Web培訓(xùn),Web前端開發(fā)培訓(xùn)

public class TestEvent {    private int mMsg;    public TestEvent(int msg) {
        mMsg = msg;
    }    public int getMsg(){        return mMsg;
    }
}

電腦培訓(xùn),計算機培訓(xùn),平面設(shè)計培訓(xùn),網(wǎng)頁設(shè)計培訓(xùn),美工培訓(xùn),Web培訓(xùn),Web前端開發(fā)培訓(xùn)

這個類很簡單,只有一個變量和一個構(gòu)造方法、get方法。具體內(nèi)容根據(jù)項目需求來定。

基本上了解這些就可以搞明白EventBus的使用了,下面上一下我寫的Demo,功能很簡單,就是模仿下載的進(jìn)度條,因為現(xiàn)在用的最多的是通過handler來進(jìn)行處理的,而EventBus的出現(xiàn),可以完美的代替handler,

而且實現(xiàn)了解耦。

好,上代碼!

MainActivity.class

電腦培訓(xùn),計算機培訓(xùn),平面設(shè)計培訓(xùn),網(wǎng)頁設(shè)計培訓(xùn),美工培訓(xùn),Web培訓(xùn),Web前端開發(fā)培訓(xùn)

package com.example.wgh.eventbusdemo;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.ProgressBar;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;public class MainActivity extends Activity {    public ProgressBar progressBar = null;    public int time = 0;
    @Override    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
            @Override            public void onClick(View v) {                new Thread(new Runnable() {
                    @Override                    public void run() {                        while (time<100){
                            time += 15;
                            EventBus.getDefault().post(new TestEvent(time));                            try {
                                Thread.sleep(200);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }).start();
            }
        });
        progressBar = (ProgressBar) findViewById(R.id.progressbar);

        EventBus.getDefault().register(this);
    }

    @Override    protected void onDestroy() {
        super.onDestroy();
        EventBus.getDefault().unregister(this);
    }
    @Subscribe(threadMode = ThreadMode.MAIN)    public void onEventMainThread(TestEvent event){
        progressBar.setProgress(event.getMsg());
    }
}

電腦培訓(xùn),計算機培訓(xùn),平面設(shè)計培訓(xùn),網(wǎng)頁設(shè)計培訓(xùn),美工培訓(xùn),Web培訓(xùn),Web前端開發(fā)培訓(xùn)

activity_main.xml

電腦培訓(xùn),計算機培訓(xùn),平面設(shè)計培訓(xùn),網(wǎng)頁設(shè)計培訓(xùn),美工培訓(xùn),Web培訓(xùn),Web前端開發(fā)培訓(xùn)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.wgh.eventbusdemo.MainActivity"
    android:orientation="vertical">

    <ProgressBar
        android:id="@+id/progressbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="150dp"
        android:max="100"
        style="@style/Widget.AppCompat.ProgressBar.Horizontal"/>
    <Button
        android:id="@+id/button"
        android:layout_marginTop="10dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="開始下載"/>
</LinearLayout>

電腦培訓(xùn),計算機培訓(xùn),平面設(shè)計培訓(xùn),網(wǎng)頁設(shè)計培訓(xùn),美工培訓(xùn),Web培訓(xùn),Web前端開發(fā)培訓(xùn)

TestEvent.class

電腦培訓(xùn),計算機培訓(xùn),平面設(shè)計培訓(xùn),網(wǎng)頁設(shè)計培訓(xùn),美工培訓(xùn),Web培訓(xùn),Web前端開發(fā)培訓(xùn)

public class TestEvent {    private int mMsg;    public TestEvent(int msg) {
        mMsg = msg;
    }    public int getMsg(){        return mMsg;
    }
}

電腦培訓(xùn),計算機培訓(xùn),平面設(shè)計培訓(xùn),網(wǎng)頁設(shè)計培訓(xùn),美工培訓(xùn),Web培訓(xùn),Web前端開發(fā)培訓(xùn)

http://www.cnblogs.com/upwgh/p/6394901.html