EventBus 3.0使用詳解

01 前言

當咱們進行項目開發的時候,每每是須要應用程序的各組件、組件與後臺線程間進行通訊,好比在子線程中進行請求數據,當數據請求完畢後經過Handler或者是廣播通知UI,而兩個Fragment之家能夠經過Listener進行通訊等等。當咱們的項目愈來愈複雜,使用Intent、Handler、Broadcast進行模塊間通訊、模塊與後臺線程進行通訊時,代碼量大,並且高度耦合。如今就讓咱們來學習一下EventBus 3.0吧。android

02 什麼是EventBus

EventBus源碼詳解git

EventBus Github地址
進入官網,看看人家是怎麼解釋的:github

  • 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可以簡化各組件間的通訊,讓咱們的代碼書寫變得簡單,能有效的分離事件發送方和接收方(也就是解耦的意思),能避免複雜和容易出錯的依賴性和生命週期問題。app

03 關於EventBus的概述

三要素

  • Event 事件。它能夠是任意類型。
  • Subscriber 事件訂閱者。在EventBus3.0以前咱們必須定義以onEvent開頭的那幾個方法,分別是onEvent、onEventMainThread、onEventBackgroundThread和onEventAsync,而在3.0以後事件處理的方法名能夠隨意取,不過須要加上註解@subscribe(),而且指定線程模型,默認是POSTING。
  • Publisher 事件的發佈者。咱們能夠在任意線程裏發佈事件,通常狀況下,使用EventBus.getDefault()就能夠獲得一個EventBus對象,而後再調用post(Object)方法便可。

四種線程模型

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

  • POSTING (默認) 表示事件處理函數的線程跟發佈事件的線程在同一個線程。
  • MAIN 表示事件處理函數的線程在主線程(UI)線程,所以在這裏不能進行耗時操做。
  • BACKGROUND 表示事件處理函數的線程在後臺線程,所以不能進行UI操做。若是發佈事件的線程是主線程(UI線程),那麼事件處理函數將會開啓一個後臺線程,若是果發佈事件的線程是在後臺線程,那麼事件處理函數就使用該線程。
  • ASYNC 表示不管事件發佈的線程是哪個,事件處理函數始終會新建一個子線程運行,一樣不能進行UI操做。

04 EventBus的基本用法

舉個例子,我須要在一個Activity裏註冊EventBus事件,而後定義接收方法,這跟Android裏的廣播機制很像,你須要首先註冊廣播,而後須要編寫內部類,實現接收廣播,而後操做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類,裏面定義用來傳輸的數據的類型。post

註冊事件

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

發送事件

EventBus.getDefault().post(messageEvent);

處理事件

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

前面咱們說過,處理消息的方法名字能夠隨便取。可是須要加一個註解@Subscribe,而且要指定線程模型。ui

4.1 EventBus用法之:粘性事件

所謂粘性事件,就是在發送事件以後再訂閱該事件也能收到該事件。請注意這裏與普通事件的區別,普通事件是先註冊在綁定。
好比在項目中有這樣的需求,在FirstActivity發送事件,到SecondActivity中作事件的處理。若是是使經過EventBus.getDefault.post(xx)發出的,在SecondActivity是接收不到消息的。 主要緣由是SecondActivit用於接收消息的EventBus還未完成註冊,也就是發佈者發了消息,但訂閱者還未產生。this

發送粘性事件

EventBus.getDefault().postSticky(messageEvent);

以Sticky的形式發送的事件,在註冊對象也要經過Sticky的形式進行處理事件

處理粘性事件

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

剩下的註冊操做和解綁操做和發送普通事件是同樣的

05 EventBus使用實戰

以上咱們講了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裏去進行事件的發送。

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

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

運行程序。

在FirstActivity中,左邊是一個按鈕,點擊以後能夠跳轉到SecondActivity,在按鈕的右邊是一個TextView,用來進行結果的驗證。

 

這是SecondActivity,在頁面的左上角,是一個按鈕,當點擊按鈕,就會發送了一個事件,最後這個Activity就會銷燬掉。

此時咱們能夠看到,FirstActivity裏的文字已經變成了,咱們在SecondActivity裏設置的文字。

總結

通過這個簡單的例子,咱們發現EventBus使用起來是如此的方便,當咱們的代碼量變得不少的時候,使用EventBus後你的邏輯很是的清晰,而且代碼之間高度解耦,在進行組件、頁面間通訊的時候,EventBus是一個不錯的選擇。

相關文章
相關標籤/搜索