EventBus 3.0使用詳解

01 前言

當(dāng)我們進(jìn)行項(xiàng)目開(kāi)發(fā)的時(shí)候,往往是需要應(yīng)用程序的各組件、組件與后臺(tái)線程間進(jìn)行通信,比如在子線程中進(jìn)行請(qǐng)求數(shù)據(jù),當(dāng)數(shù)據(jù)請(qǐng)求完畢后通過(guò)Handler或者是廣播通知UI,而兩個(gè)Fragment之家可以通過(guò)Listener進(jìn)行通信等等。當(dāng)我們的項(xiàng)目越來(lái)越復(fù)雜,使用Intent、Handler、Broadcast進(jìn)行模塊間通信、模塊與后臺(tái)線程進(jìn)行通信時(shí),代碼量大,而且高度耦合?,F(xiàn)在就讓我們來(lái)學(xué)習(xí)一下EventBus 3.0吧。

02 什么是EventBus

EventBus源碼詳解

EventBus Github地址
進(jìn)入官網(wǎng),看看人家是怎么解釋的:

  • simplifies the communication between components
    decouples event senders and receivers
    performs well with Activities, Fragments, and background threads
    avoids complex and error-prone dependencies and life cycle issues
  • makes your code simpler
  • is fast
  • is tiny (~50k jar)
  • is proven in practice by apps with 100,000,000+ installs
  • has advanced features like delivery threads, subscriber priorities, etc.

大概的意思就是:EventBus能夠簡(jiǎn)化各組件間的通信,讓我們的代碼書(shū)寫(xiě)變得簡(jiǎn)單,能有效的分離事件發(fā)送方和接收方(也就是解耦的意思),能避免復(fù)雜和容易出錯(cuò)的依賴性和生命周期問(wèn)題。

03 關(guān)于EventBus的概述

三要素

  • Event 事件。它可以是任意類(lèi)型。
  • Subscriber 事件訂閱者。在EventBus3.0之前我們必須定義以onEvent開(kāi)頭的那幾個(gè)方法,分別是onEvent、onEventMainThread、onEventBackgroundThread和onEventAsync,而在3.0之后事件處理的方法名可以隨意取,不過(guò)需要加上注解@subscribe(),并且指定線程模型,默認(rèn)是POSTING。
  • Publisher 事件的發(fā)布者。我們可以在任意線程里發(fā)布事件,一般情況下,使用EventBus.getDefault()就可以得到一個(gè)EventBus對(duì)象,然后再調(diào)用post(Object)方法即可。

四種線程模型

EventBus3.0有四種線程模型,分別是:

  • POSTING (默認(rèn)) 表示事件處理函數(shù)的線程跟發(fā)布事件的線程在同一個(gè)線程。
  • MAIN 表示事件處理函數(shù)的線程在主線程(UI)線程,因此在這里不能進(jìn)行耗時(shí)操作。
  • BACKGROUND 表示事件處理函數(shù)的線程在后臺(tái)線程,因此不能進(jìn)行UI操作。如果發(fā)布事件的線程是主線程(UI線程),那么事件處理函數(shù)將會(huì)開(kāi)啟一個(gè)后臺(tái)線程,如果果發(fā)布事件的線程是在后臺(tái)線程,那么事件處理函數(shù)就使用該線程。
  • ASYNC 表示無(wú)論事件發(fā)布的線程是哪一個(gè),事件處理函數(shù)始終會(huì)新建一個(gè)子線程運(yùn)行,同樣不能進(jìn)行UI操作。

04 EventBus的基本用法

舉個(gè)例子,我需要在一個(gè)Activity里注冊(cè)EventBus事件,然后定義接收方法,這跟Android里的廣播機(jī)制很像,你需要首先注冊(cè)廣播,然后需要編寫(xiě)內(nèi)部類(lèi),實(shí)現(xiàn)接收廣播,然后操作UI。所以,在EventBus中,你同樣得這么做。

自定義一個(gè)事件類(lèi)

public class MessageEvent{
    private String message;
    public  MessageEvent(String message){
        this.message=message;
    }
    public String getMessage() {
        return message;
    }
 
    public void setMessage(String message) {
        this.message = message;
    }
}

這里有些同學(xué),會(huì)有一些疑問(wèn),為什么要建立這樣一個(gè)類(lèi),有什么用途。其實(shí)這個(gè)類(lèi)就是一個(gè)Bean類(lèi),里面定義用來(lái)傳輸?shù)臄?shù)據(jù)的類(lèi)型。

注冊(cè)事件

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

當(dāng)我們需要在Activity或者Fragment里訂閱事件時(shí),我們需要注冊(cè)EventBus。我們一般選擇在Activity的onCreate()方法里去注冊(cè)EventBus,在onDestory()方法里,去解除注冊(cè)。

解除注冊(cè)

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

發(fā)送事件

EventBus.getDefault().post(messageEvent);

處理事件

@Subscribe(threadMode = ThreadMode.MAIN)
public void XXX(MessageEvent messageEvent) {
    ...
}

前面我們說(shuō)過(guò),處理消息的方法名字可以隨便取。但是需要加一個(gè)注解@Subscribe,并且要指定線程模型。

4.1 EventBus用法之:粘性事件

所謂粘性事件,就是在發(fā)送事件之后再訂閱該事件也能收到該事件。請(qǐng)注意這里與普通事件的區(qū)別,普通事件是先注冊(cè)在綁定。
比如在項(xiàng)目中有這樣的需求,在FirstActivity發(fā)送事件,到SecondActivity中做事件的處理。如果是使通過(guò)EventBus.getDefault.post(xx)發(fā)出的,在SecondActivity是接收不到消息的。 主要原因是SecondActivit用于接收消息的EventBus還未完成注冊(cè),也就是發(fā)布者發(fā)了消息,但訂閱者還未產(chǎn)生。

發(fā)送粘性事件

EventBus.getDefault().postSticky(messageEvent);

以Sticky的形式發(fā)送的事件,在注冊(cè)對(duì)象也要通過(guò)Sticky的形式進(jìn)行處理事件

處理粘性事件

@Subscribe(threadMode = ThreadMode.MAIN,sticky = true)
public void XXX(MessageEvent messageEvent) {
    ...
}

剩下的注冊(cè)操作和解綁操作和發(fā)送普通事件是一樣的

05 EventBus使用實(shí)戰(zhàn)

以上我們講了EventBus的基本用法,沒(méi)有用過(guò)的同學(xué)也不要擔(dān)心不會(huì)用,小編在這里舉個(gè)小栗子。

第一步:添加依賴

 compile 'org.greenrobot:eventbus:3.0.0'

第二步:定義消息事件類(lèi)

public class MessageEvent{
    private String message;
    public  MessageEvent(String message){
        this.message=message;
    }
 
    public String getMessage() {
        return message;
    }
 
    public void setMessage(String message) {
        this.message = message;
    }
}

第三步:注冊(cè)和解除注冊(cè)

分別在FirstActivity的onCreate()方法和onDestory()方法里,進(jìn)行注冊(cè)EventBus和解除注冊(cè)。

package com.example.lenovo.testapp.ui;

import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import com.example.lenovo.testapp.R;
import com.example.lenovo.testapp.event.MessageEvent;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;

/**
 * Created by ZZG on 2018/1/10.
 */

public class FirstActivity extends AppCompatActivity {
    private Button mButton;
    private TextView mText;
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.first_activity);
        mButton = (Button) findViewById(R.id.btn1);
        mText = (TextView) findViewById(R.id.tv1); 
        mText.setText("今天是星期三"); 
        EventBus.getDefault().register(this);
        jumpActivity();
    }

    private void jumpActivity() {

        mButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent=new Intent(FirstActivity.this,SecondActivity.class);
                startActivity(intent);
            }
        });
    }


    @Subscribe(threadMode = ThreadMode.MAIN)
    public void Event(MessageEvent messageEvent) {
        mText.setText(messageEvent.getMessage());
    }

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

}

事件處理

在這里,事件的處理線程在主線程,是因?yàn)?,我要讓TextView去顯示值。
在 SecondActivity里去進(jìn)行事件的發(fā)送。

package com.example.lenovo.tezs;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;

import org.greenrobot.eventbus.EventBus;

/**
 * Created by ZZG on 2018/1/10.
 */

public class SecondActivity extends AppCompatActivity {
    private Button mButton2;
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.second_activity);
        mButton2=(Button) findViewById(R.id.btn2);
        jumpActivity();
    }

    private void jumpActivity() {
        mButton2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                EventBus.getDefault().post(new MessageEvent("歡迎大家瀏覽我寫(xiě)的博客"));
                finish();
            }
        });
    }
}

很簡(jiǎn)單,當(dāng)點(diǎn)擊按鈕的時(shí)候,發(fā)送了一個(gè)事件。

運(yùn)行程序。

1.PNG

在FirstActivity中,左邊是一個(gè)按鈕,點(diǎn)擊之后可以跳轉(zhuǎn)到SecondActivity,在按鈕的右邊是一個(gè)TextView,用來(lái)進(jìn)行結(jié)果的驗(yàn)證。
2.PNG

這是SecondActivity,在頁(yè)面的左上角,是一個(gè)按鈕,當(dāng)點(diǎn)擊按鈕,就會(huì)發(fā)送了一個(gè)事件,最后這個(gè)Activity就會(huì)銷(xiāo)毀掉。


3.PNG

此時(shí)我們可以看到,F(xiàn)irstActivity里的文字已經(jīng)變成了,我們?cè)赟econdActivity里設(shè)置的文字。

總結(jié)

經(jīng)過(guò)這個(gè)簡(jiǎn)單的例子,我們發(fā)現(xiàn)EventBus使用起來(lái)是如此的方便,當(dāng)我們的代碼量變得很多的時(shí)候,使用EventBus后你的邏輯非常的清晰,并且代碼之間高度解耦,在進(jìn)行組件、頁(yè)面間通信的時(shí)候,EventBus是一個(gè)不錯(cuò)的選擇。

Android技術(shù)討論Q群:947460837

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 目錄 1.概述 2.實(shí)戰(zhàn) 1.基本框架搭建 2.新建一個(gè)類(lèi)FirstEvent 3.在要接收消息的頁(yè)面注冊(cè)Even...
    慕涵盛華閱讀 10,631評(píng)論 2 16
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,323評(píng)論 25 708
  • 前言:EventBus出來(lái)已經(jīng)有一段時(shí)間了,github上面也有很多開(kāi)源項(xiàng)目中使用了EventBus。所以抽空學(xué)習(xí)...
    Kerry202閱讀 1,373評(píng)論 1 2
  • ——lihua’s隨想記1752...
    lihua看世界閱讀 653評(píng)論 0 1
  • 隨著《羋月傳》和《大秦帝國(guó)之崛起》的熱播,秦朝以及戰(zhàn)國(guó)波瀾壯闊風(fēng)云激蕩的歷史畫(huà)面再次展現(xiàn)在了人們面前?!洞笄氐蹏?guó)》...
    沙鷗_f44c閱讀 807評(píng)論 1 5

友情鏈接更多精彩內(nèi)容