EventBus 3.0使用詳解

01 前言

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

02 什么是EventBus

EventBus源碼詳解

EventBus Github地址
進入官網(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能夠簡化各組件間的通信,讓我們的代碼書寫變得簡單,能有效的分離事件發(fā)送方和接收方(也就是解耦的意思),能避免復雜和容易出錯的依賴性和生命周期問題。

03 關于EventBus的概述

三要素

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

四種線程模型

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

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

04 EventBus的基本用法

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

自定義一個事件類

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;
    }
}

這里有些同學,會有一些疑問,為什么要建立這樣一個類,有什么用途。其實這個類就是一個Bean類,里面定義用來傳輸?shù)臄?shù)據(jù)的類型。

注冊事件

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

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

解除注冊

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

發(fā)送事件

EventBus.getDefault().post(messageEvent);

處理事件

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

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

4.1 EventBus用法之:粘性事件

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

發(fā)送粘性事件

EventBus.getDefault().postSticky(messageEvent);

以Sticky的形式發(fā)送的事件,在注冊對象也要通過Sticky的形式進行處理事件

處理粘性事件

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

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

05 EventBus使用實戰(zhàn)

以上我們講了EventBus的基本用法,沒有用過的同學也不要擔心不會用,小編在這里舉個小栗子。

第一步:添加依賴

 compile 'org.greenrobot:eventbus:3.0.0'

第二步:定義消息事件類

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;
    }
}

第三步:注冊和解除注冊

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

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);
        }
    }

}

事件處理

在這里,事件的處理線程在主線程,是因為,我要讓TextView去顯示值。
在 SecondActivity里去進行事件的發(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("歡迎大家瀏覽我寫的博客"));
                finish();
            }
        });
    }
}

很簡單,當點擊按鈕的時候,發(fā)送了一個事件。

運行程序。

1.PNG

在FirstActivity中,左邊是一個按鈕,點擊之后可以跳轉到SecondActivity,在按鈕的右邊是一個TextView,用來進行結果的驗證。
2.PNG

這是SecondActivity,在頁面的左上角,是一個按鈕,當點擊按鈕,就會發(fā)送了一個事件,最后這個Activity就會銷毀掉。


3.PNG

此時我們可以看到,F(xiàn)irstActivity里的文字已經(jīng)變成了,我們在SecondActivity里設置的文字。

總結

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

Android技術討論Q群:947460837

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

相關閱讀更多精彩內容

友情鏈接更多精彩內容