天天看点

Android开源项目EventBus3.0的使用

前言:

 EventBus,是一个针对Android优化的事件订阅/发表开源项目,可以替代Intent,,BroadCast在Fragment,Activity,Service,线程之间传递消息.优点是开销小,代码更优雅,以及将发送者和接收者解耦。

EventBus3.0下载:EventBus3.0,将下载的jar包引入项目中就可以使用了。

正确的使用步骤:

  1. 注册事件订阅者(”登录”)
  2. 发送方发送消息(传递数据)
  3. 接收方处理消息(处理数据)
  4. 解除注册(”注销”)

1. 注册事件订阅者(”登录”)

// 1.注册事件订阅者("登录")
EventBus.getDefault().register(this);  
           

这里将当前的这个对象注册到EventBus事件总线中,在android中通常是在Application、Activity、Service、Fragment的onCreate方法中进行。

如:

@Override  
protected void onCreate(Bundle savedInstanceState) {  
    super.onCreate(savedInstanceState);  
    setContentView(R.layout.activity_main);
    // 1.注册事件订阅者("登录")
    EventBus.getDefault().register(this);  
}
           

2. 发送方发送消息(传递数据)

// 2.发送方发送消息 -- 发送MainMessage这个自己定义的对象,可以丰富这个对象,用来传递消息(数据)
EventBus.getDefault().post(new MainMessage("Hello EventBus"));  
           
// 2.发送方发送消息 -- 发送BackgroundMessage这个自己定义的对象,可以丰富这个对象,用来传递消息(数据)
EventBus.getDefault().post(new BackgroundMessage("Hello EventBus"));
           
// 2.发送方发送消息 -- 发送AsyncMessage这个自己定义的对象,可以丰富这个对象,用来传递消息(数据)
EventBus.getDefault().post(new AsyncMessage("Hello EventBus"));
           
// 2.发送方发送消息 -- 发送PostMessage这个自己定义的对象,可以丰富这个对象,用来传递消息(数据)
EventBus.getDefault().post(new PostMessage("Hello EventBus"));  
           

注:这三段代码都属于第二步,只不过发送的消息对象类型(类)不同,这里的消息对象MainMessage,BackgroundMessage,AsyncMessage和PostMessage是我们自己定义的用来传递消息(数据)的对象,可以自行丰富(这些消息对象之间没有继承关系,是不同类型的对象)。

而这些对象的源码(这里都类似,自行丰富):

package com.example.eventbus;

public class MainMessage {
    private String msg;

    public MainMessage(String msg){
        this.msg = msg;
    }

    public String getMsg() {
        return msg;
    }
}
           

3. 接收方处理消息(处理数据)

// 3.接收方处理消息(处理数据)-- 主线程中执行  
@Subscribe(threadMode = ThreadMode.MainThread)  
public void onMainEventBus(MainMessage msg) {  
    Log.d(TAG, "onEventBus() handling message: " + Thread.currentThread().getName());  
}  
           
// 3.接收方处理消息(处理数据)-- 后台线程或子线程中执行
@Subscribe(threadMode = ThreadMode.BackgroundThread)  
public void onBackgroundEventBus(BackgroundMessage msg) {  
    Log.d(TAG, "onEventBusBackground() handling message: " + Thread.currentThread().getName());  
}  
           
// 3.接收方处理消息(处理数据)-- 后台线程中执行  
@Subscribe(threadMode = ThreadMode.Async)  
public void onAsyncEventBus(AsyncMessage msg) { 
    Log.d(TAG, "onEventBusAsync() handling message: " + Thread.currentThread().getName());  
}  
           
// 3.接收方处理消息(处理数据)-- 和发送方在同一个线程  
@Subscribe(threadMode = ThreadMode.PostThread)  
public void onPostEventBus(PostMessage msg) {  
    Log.d(TAG, "onEventBusPost() handling message: " + Thread.currentThread().getName());  
}
           

注:

  1. 这三段代码都属于第三步,分别对应第二步中发送的不同消息对象类型;
  2. 方法参数的对象类型很重要,EventBus会根据这里的参数对象类型判断应该调用哪个回调方法(可能是多个),也就是说上面的第二步中发送的4种不同类型的对象会分别回调对应参数类型的那个事件处理方法。这里判断对应参数类型是根据发送的对象消息类型是否是方法参数对象的类型或者子类(这也就是为什么在第二步中说明那4个消息对象是不同类型,没有继承关系),如果发送的对象消息类型是方法参数对象的类型或者子类,那么就会回调这个方法(顺序是先本类再父类);
  3. 事件处理方法上面的注解

    @Subscribe(threadMode = ThreadMode.*)

    必不可少,是为了指定当前处理方法的线程模型,即:
    1. @Subscribe(threadMode = ThreadMode.MainThread):不管发送方在那个线程发送的消息,接收方(处理方)都在主线程中处理消息(数据),注意主线程不要被阻塞;
    2. @Subscribe(threadMode = ThreadMode.BackgroundThread):如果发送方在主线程中发送消息,那么接收方(处理方)就会在后台线程中处理消息,否则在和发送方相同的那个子线程中处理消息(数据);
    3. @Subscribe(threadMode = ThreadMode.Async):强制接收方(处理方)在后台线程中处理消息(数据);
    4. @Subscribe(threadMode = ThreadMode.PostThread):和发送方在相同的线程中处理消息(数据)。
  4. 方法名可以任意,只要符合命名规则就行;
  5. 注意,后台线程可以有多个,即如果一个后台线程被阻塞后新的消息到达后会在一个新的后台线程处理消息。

4. 解除注册(”注销”)

// 4.解除注册("注销")
EventBus.getDefault().unregister(this);  
           

这里将当前的这个对象从EventBus事件总线中解除注册,在android中通常是在Activity、Service和Fragment的onDestroy方法中进行。

如:

@Override  
 protected void onDestroy() {  
     super.onDestroy();  
     // 4.解除注册("注销")
     EventBus.getDefault().unregister(this);  
 }  
           

完成这四步后,接下来就看看项目的完整代码:

MainActivity.java

package com.example.eventbus;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import de.greenrobot.event.EventBus;
import de.greenrobot.event.Subscribe;
import de.greenrobot.event.ThreadMode;

public class MainActivity extends Activity {

    private final static String TAG = "EventBusTest";  

    @Override  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.activity_main);
        // 1.注册事件订阅者("登录")
        EventBus.getDefault().register(this);  
    }  

    @Override  
    protected void onDestroy() {  
        super.onDestroy();  
        // 4.解除注册("注销")
        EventBus.getDefault().unregister(this);  
    }  

    public void testActivity(View view){
        Intent intent = new Intent(this,TestActivity.class);
        startActivity(intent);
    }

    // 3.接收方处理消息(处理数据)-- 主线程中执行  
    @Subscribe(threadMode = ThreadMode.MainThread)  
    public void onMainEventBus(MainMessage msg) {  
        Log.d(TAG, "onEventBus() handling message: " + Thread.currentThread().getName());  
    }  

    // 3.接收方处理消息(处理数据)-- 后台线程或子线程中执行
    @Subscribe(threadMode = ThreadMode.BackgroundThread)  
    public void onBackgroundEventBus(BackgroundMessage msg) {  
        Log.d(TAG, "onEventBusBackground() handling message: " + Thread.currentThread().getName());  
    }  

    // 3.接收方处理消息(处理数据)-- 后台线程中执行  
    @Subscribe(threadMode = ThreadMode.Async)  
    public void onAsyncEventBus(AsyncMessage msg) { 
        Log.d(TAG, "onEventBusAsync() handling message: " + Thread.currentThread().getName());  
    }  

    // 3.接收方处理消息(处理数据)-- 和发送方在同一个线程  
    @Subscribe(threadMode = ThreadMode.PostThread)  
    public void onPostEventBus(PostMessage msg) {  
        Log.d(TAG, "onEventBusPost() handling message: " + Thread.currentThread().getName());  
    }  
}
           

activity_main.xml

<LinearLayout  
    xmlns:android="http://schemas.android.com/apk/res/android"  
    xmlns:tools="http://schemas.android.com/tools"  
    android:layout_width="match_parent"  
    android:layout_height="match_parent"
    android:gravity="center"  
    android:orientation="vertical">  

    <Button 
        android:onClick="testActivity"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="testActivity"
        />

</LinearLayout>  
           

OtherActivity.java(注意在清单文件里注册哦)

package com.example.eventbus;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import de.greenrobot.event.EventBus;

public class OtherActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.other_activity);
    }

    public void btnClick(View view) {  
        switch (view.getId()) {  
            case R.id.btn1:  
                // 2.发送方发送消息 -- 发送MainMessage这个自己定义的对象,可以丰富这个对象,用来传递消息(数据)
                EventBus.getDefault().post(new MainMessage("Hello EventBus"));  
                break;  
            case R.id.btn2:
                // 2.发送方发送消息 -- 发送BackgroundMessage这个自己定义的对象,可以丰富这个对象,用来传递消息(数据)
                // 注意,这里是在主线程中发送消息
                EventBus.getDefault().post(new BackgroundMessage("Hello EventBus"));  
                break;  
            case R.id.btn3:  
                new Thread(){
                    public void run() {
                        // 2.发送方发送消息 -- 发送AsyncMessage这个自己定义的对象,可以丰富这个对象,用来传递消息(数据)
                        EventBus.getDefault().post(new AsyncMessage("Hello EventBus"));  
                    };
                }.start();
                break;  
            case R.id.btn4:  
                new Thread(){
                    public void run() {
                        // 2.发送方发送消息 -- 发送PostMessage这个自己定义的对象,可以丰富这个对象,用来传递消息(数据)
                        EventBus.getDefault().post(new PostMessage("Hello EventBus"));  
                    };
                }.start();
                break;  
        }  
    }  
}
           

other_activity.xml

<LinearLayout  
    xmlns:android="http://schemas.android.com/apk/res/android"  
    xmlns:tools="http://schemas.android.com/tools"  
    android:layout_width="match_parent"  
    android:layout_height="match_parent"  
    android:orientation="vertical">  

    <Button  
        android:id="@+id/btn1"  
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"  
        android:onClick="btnClick"  
        android:text="发送消息强制接收方在主线程处理消息"/>  

    <Button  
        android:id="@+id/btn2"  
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"  
        android:onClick="btnClick"  
        android:text="发送消息让接收方在后台线程或子线程处理消息"/>  

    <Button  
        android:id="@+id/btn3"  
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"  
        android:onClick="btnClick"  
        android:text="发送消息强制接收方在后台线程中处理消息"/>  

    <Button  
        android:id="@+id/btn4"  
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"  
        android:onClick="btnClick"  
        android:text="发送消息让接收方在发送方所在的线程处理消息"/>  

</LinearLayout>  
           

这里可能会问,为什么不在一个activity中进行发送消息和处理消息呢?其实,这里我这样做是为了说明,EventBus起的作用和Broadcast作用一样,可以使得不同的Activity进行通讯,对比使用上也可以发现同样需要注册和取消注册,关于里面的原理,可能是通过观察者模式来实现的吧。

接下来,我们就只需要观察测试结果了:

运行起这个程序,在OtherActivity中分别点击四个按钮,然后观察日志打印:

Android开源项目EventBus3.0的使用

到这里,EventBus的基本使用已经说完了,如果文章中有什么不理解或是遇到什么困惑的话不妨自己动手实验一下,毕竟实验是检验真理的唯一标准!这里是本文演示的项目下载地址,方便下载测试:

demo下载地址:http://download.csdn.net/detail/ydxlt/9441708

参考文章:http://blog.csdn.net/u012702547/article/details/50688236