EventBus的使用和原理在网上有很多的博客了,其中泓洋大哥启舰写的非常非常棒,我也是跟着他们的博客学会的EventBus,因为是第一次接触并使用EventBus,所以我写的更多是如何使用,源码解析就不怎么样啦!

如需转载请注明出处:Android EventBus 3.0 实例使用详解

电脑培训,计算机培训,平面设计培训,网页设计培训,美工培训,Web培训,Web前端开发培训

一、概述

EventBus是一款Android下的发布/订阅事件总线机制。可以代替Intent、Handler、Broadcast等在Fragment、Activity之间传递消息。

优点:开销小,代码优雅。将发送者和接受者解耦。

既然是有关于事件的发布和订阅,那么发布者和订阅者的关系又是怎样的呢?

事件的发布者可以发布多个事件,发布者同时也可以是订阅者,订阅者可以订阅多个事件。

二、实例

接下来要通过实例来讲解如何使用EventBus了,在看代码之前要记得三个问题。

1、事件发布者如何发布事件

2、事件订阅者如何订阅事件

3、订阅者如何准确接收发布者发布的多个事件中的一个(假设发布者发布多个事件,订阅者只是订阅其中的一个事件)

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

compile 'org.greenrobot:eventbus:3.0.0'

(2)在相关Activity中的onCreat()、onDestory()注册和解注EventBus

电脑培训,计算机培训,平面设计培训,网页设计培训,美工培训,Web培训,Web前端开发培训

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

电脑培训,计算机培训,平面设计培训,网页设计培训,美工培训,Web培训,Web前端开发培训

(3)事件发布者如何发布事件

EventBus.getDefault().post(实参);

我们到.getDefault()来看一个这个方法:

电脑培训,计算机培训,平面设计培训,网页设计培训,美工培训,Web培训,Web前端开发培训

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

电脑培训,计算机培训,平面设计培训,网页设计培训,美工培训,Web培训,Web前端开发培训

这里的.getDefault()方法其实就是一个单例,获取到EventBus实例后调用post方法开始发布事件

post():

电脑培训,计算机培训,平面设计培训,网页设计培训,美工培训,Web培训,Web前端开发培训

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

电脑培训,计算机培训,平面设计培训,网页设计培训,美工培训,Web培训,Web前端开发培训

通过源码可以看得出来,方法的实参是一个对象类型的参数,参数会统一存储在eventQueue这个队列中,然后循环队列,将队列中的消息逐一发布,这里大家可能会想,每次post都会去调用整个队列么,那么不会造成方法多次调用么?

答案是不会的,因为在最外层加了一个判断,判断event是否被发不过,如果被发布过,则不会进入到这个方法内。

(4)事件订阅者订阅事件

@Subscribe    public void onEventMainThread(实参){        //接收到发布者发布的事件后,进行相应的处理操作
    }

这里要注意的是:EventBus在 3.0 版本后,事件订阅监听的方法名可以随意起,不同于旧版本,名字是特定的。

电脑培训,计算机培训,平面设计培训,网页设计培训,美工培训,Web培训,Web前端开发培训

public void onEventMainThread(param)  
    {  
    //如果使用onEventMainThread作为订阅函数,那么不论事件是在哪个线程中发布出来的,onEventMainThread都会在UI线程中执行,接收事件就会在UI线程中运行,
   //这个在Android中是非常有用的,因为在Android中只能在UI线程中跟新UI,所以在onEvnetMainThread方法中是不能执行耗时操作的。
   }            
public void onEventPostThread(param)      {       //如果使用onEvent作为订阅函数,那么该事件在哪个线程发布出来的,onEvent就会在这个线程中运行,也就是说发布事件和接收事件线程在同一个线程。
    //使用这个方法时,在onEvent方法中不能执行耗时操作,如果执行耗时操作容易导致事件分发延迟。
       }            
public void onEventBackgroundThread(param)      {       //如果使用onEventBackgrond作为订阅函数,那么如果事件是在UI线程中发布出来的,那么onEventBackground就会在子线程中运行,如果事件本来就是子线程中发布出来的,那么onEventBackground函数直接在该子线程中执行。        }            public void onEventAsync(param)      {     //使用这个函数作为订阅函数,那么无论事件在哪个线程发布,都会创建新的子线程在执行onEventAsync.            }

电脑培训,计算机培训,平面设计培训,网页设计培训,美工培训,Web培训,Web前端开发培训

但是新版本需要手动的添加注解@Subscribe(这是必不可少的)。既然名字可以随意起,那么又怎么控制在什么线程内进行处理呢?

@Subscribe(threadMode = ThreadMode.MAIN)

给注解设置ThreadMode就可以了。

(5)事件发布者和订阅者如何对应上

可以看到发布事件和订阅事件,都需要传入一个实参,而且在post方法中我们也看到了,这个实参是对象类型的,大家猜想的话也可以知道,发布和订阅事件是通过一个对象实参来进行关联的。

电脑培训,计算机培训,平面设计培训,网页设计培训,美工培训,Web培训,Web前端开发培训

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

电脑培训,计算机培训,平面设计培训,网页设计培训,美工培训,Web培训,Web前端开发培训

这个类很简单,只有一个变量和一个构造方法、get方法。具体内容根据项目需求来定。

基本上了解这些就可以搞明白EventBus的使用了,下面上一下我写的Demo,功能很简单,就是模仿下载的进度条,因为现在用的最多的是通过handler来进行处理的,而EventBus的出现,可以完美的代替handler,

而且实现了解耦。

好,上代码!

MainActivity.class

电脑培训,计算机培训,平面设计培训,网页设计培训,美工培训,Web培训,Web前端开发培训

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

电脑培训,计算机培训,平面设计培训,网页设计培训,美工培训,Web培训,Web前端开发培训

activity_main.xml

电脑培训,计算机培训,平面设计培训,网页设计培训,美工培训,Web培训,Web前端开发培训

<?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>

电脑培训,计算机培训,平面设计培训,网页设计培训,美工培训,Web培训,Web前端开发培训

TestEvent.class

电脑培训,计算机培训,平面设计培训,网页设计培训,美工培训,Web培训,Web前端开发培训

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

电脑培训,计算机培训,平面设计培训,网页设计培训,美工培训,Web培训,Web前端开发培训

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

网友评论