`
xiangzhihong
  • 浏览: 9278 次
  • 性别: Icon_minigender_1
  • 来自: 上海
文章分类
社区版块
存档分类
最新评论

EventBus使用详解

阅读更多

前言

最近在公司做一个类似于手机工厂模式的一个项目,用来检测其他各个App是否正常工作,所以要求是尽可能的轻量级,因为是检测其他App的工作,所以整个项目都是信息之间的频繁交互。在项目中存在很多Fragment和Fragment之间的信息交互,之前一直在用广播来实现但是广播使用起来较为麻烦且效率不高。在同事的建议下学习了EventBus,在此做一下学习记录,侵权请告知一定及时删除。

EventBus概述

  EventBus是针一款对Android的发布/订阅事件总线。它可以让我们很轻松的实现在Android各个组件之间传递消息,并且代码的可读性更好,耦合度更低。

1.基本用法

示例:

当击StartSecondActivity按钮的时候,跳到第二个Activity,当点击第二个activity上面的SendMessage按钮的时候向第一个Activity发送消息,当第一个Activity收到消息后将消息放入textView中显示。 
"/      "/ 
"/

用法:

(1)先定义一个类
public class MessageEvent {
        .......
}
  • 1
  • 2
  • 3
  • 4
(2)在需要接收消息的页面注册事件(类似于动态注册广播)
EventBus.getDefault().register(this);
  • 1
(3)发送消息
EventBus.getDefault().post(new MessageEvent()); 
  • 1
(4)处理消息( 在3.0之后,消息处理的方法可以随便取名,但是需要添加一个注解 @Subscribe,并且要指定线程模型(默认为PostThread),四种线程模型,下面会讲到。)
@Subscribe(threadMode = ThreadMode.PostThread)
public void XXX(MessageEvent messageEvent) {
    ...
} 
  • 1
  • 2
  • 3
  • 4
(5)解除注册( 类似于动态广播的解除注册)
EventBus.getDefault().post(new MessageEvent()); 
  • 1

整体的流程就是这样,注意:事件处理函数的访问权限必须为public,否则会报异常。

示例代码:

下面我将示例代码描述一下:

(1)布局
MainActivity布局(activity_main.xml)
<?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:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.example.liuhe.eventbusdemo.MainActivity">

    <TextView
        android:id="@+id/show_message"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="25sp"
        android:text="Hello World" />

    <Button
        android:id="@+id/start_second"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Start SecondActivity"/>

</LinearLayout>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
新建一个SecondActivity(second.xml)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/message"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="25sp"
        android:text="This is SecondaAtivity's message"/>

    <Button
        android:id="@+id/send"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Send Message"/>

</LinearLayout>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
(2)创建一个MessageEvent类
public class MessageEvent {

    private String message;

    public MessageEvent(String message) {
        this.message = message;
    }

    public String getMessage() {
        return message;
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

这个类很简单,只需要我们在构造方法内传入一个值,然后通过 getMessage()来获取出来。

(3)在要接受的消息的注册事件(别忘记在onDestroy()中解除注册)
@Subscribe(threadMode = ThreadMode.POSTING)
    public void showMessageMainEvent(MessageEvent messageEvent){
        show_message.setText("Message from SecondActivity" + "---" +messageEvent.getMessage());
    }
  • 1
  • 2
  • 3
  • 4
(4)发送消息
 EventBus.getDefault().post(new MessageEvent(message));
  • 1
完整代码
(1)MainActivity
public class MainActivity extends AppCompatActivity {

    private TextView show_message;
    private Button start_second;

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

        show_message = (TextView) findViewById(R.id.show_message);
        start_second = (Button) findViewById(R.id.start_second);

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

        EventBus.getDefault().register(this);

    }


    @Subscribe(threadMode = ThreadMode.POSTING)
    public void showMessagePOSTINGEvent(MessageEvent messageEvent){
        show_message.setText("Message from SecondActivity" + "---" +messageEvent.getMessage());
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        EventBus.getDefault().unregister(this);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
(2)SecondActivity
public class SecondActivity extends Activity{

    private Button button;
    private TextView textView;

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

        button = (Button) findViewById(R.id.send);
        textView = (TextView) findViewById(R.id.message);

        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String message = textView.getText().toString();
                if (TextUtils.isEmpty(message)){
                    message = "defaule message";
                }
                EventBus.getDefault().post(new MessageEvent(message));

            }
        });
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

这就是基本的使用了,上文中我们使用的是POSTING线程模型,下面介绍一下EventBus的四种线程模型。

2.四种线程模型(ThreadMode)

在写消息处理的时候,方法名字可以随意命名,但是需要通过@Subscribe注解一下当前使用的线程模型。EventBus的县城模型一共有四种:

  • POSTING(默认) 
    如果使用事件处理函数指定了线程模型为PostThread,那么该事件在哪个线程发布出来的,事件处理函数就会在这个线程中运行,也就是说发布事件和接收事件在同一个线程。在线程模型为PostThread的事件处理函数中尽量避免执行耗时操作,因为它会阻塞事件的传递,甚至有可能会引起ANR。
  • MAIN 
    不论事件是在哪个线程中发布出来的,该事件处理函数都会在UI线程中执行。该方法可以用来更新UI,但是不能处理耗时操作。
  • BACKGROUND 
    如果事件是在UI线程中发布出来的,那么该事件处理函数就会在新的线程中运行,如果事件本来就是子线程中发布出来的,那么该事件处理函数直接在发布事件的线程中执行。在此事件处理函数中禁止进行UI更新操作。
  • ASYNC 
    无论事件在哪个线程发布,该事件处理函数都会在新建的子线程中执行。同样,此事件处理函数中禁止进行UI更新操作。

示例:

1.将上面的例子加上三个处理消息的方法,分别指定为其余的三种线程模型,我们现在UI线程线程发送一条消息看看Log打印结果。

(1)MainActivity代码如下:
public class MainActivity extends AppCompatActivity {

    private TextView show_message;
    private Button start_second;

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

        show_message = (TextView) findViewById(R.id.show_message);
        start_second = (Button) findViewById(R.id.start_second);

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

        EventBus.getDefault().register(this);

    }


    @Subscribe(threadMode = ThreadMode.POSTING)
    public void showMessagePOSTINGEvent(MessageEvent messageEvent){
        show_message.setText("Message from SecondActivity" + "---" +messageEvent.getMessage());
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void showMessageMainEvent(MessageEvent messageEvent){
        show_message.setText("Message from SecondActivity" + "---" +messageEvent.getMessage());
    }

    @Subscribe(threadMode = ThreadMode.BACKGROUND)
    public void showMessageBACKGROUNDEvent(MessageEvent messageEvent){
        show_message.setText("Message from SecondActivity" + "---" +messageEvent.getMessage());
    }

    @Subscribe(threadMode = ThreadMode.ASYNC)
    public void showMessageASYNCEvent(MessageEvent messageEvent){
        show_message.setText("Message from SecondActivity" + "---" +messageEvent.getMessage());
    }


    @Override
    protected void onDestroy() {
        super.onDestroy();
        EventBus.getDefault().unregister(this);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
(2)Log如下:
D/MAIN: main
D/POSTING: main
D/ASYNC: pool-1-thread-1
D/BACKGROUND: pool-1-thread-2
  • 1
  • 2
  • 3
  • 4
  • 5

从日志打印结果可以看出,如果在UI线程中发布事件,则线程模型为POSTING的事件处理函数也执行在UI线程,与发布事件的线程一致。线程模型为ASYNC的事件处理函数执行在名字叫做pool-1-thread-1的新的线程中。而MAIN的事件处理函数执行在UI线程,BACKGROUND的时间处理函数执行在名字叫做pool-1-thread-2的新的线程中。

2.我们在子线程发送一条消息看看Log情况

button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                new Thread(new Runnable() {
                    @Override
                    public void run() {
                              Log.d("post", Thread.currentThread().getName());
                        EventBus.getDefault().post(new MessageEvent("NewMesage"));

                    }
                }).start();

            }

        });
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

Log如下:

D/post: Thread-153
D/BACKGROUND: Thread-153
D/POSTING: Thread-153
D/MAIN: main
D/ASYNC: pool-1-thread-1
  • 1
  • 2
  • 3
  • 4
  • 5

从日志打印结果不难看出,如果在子线程中发布事件,则线程模型为POSTING的事件处理函数也执行在子线程,与发布事件的线程一致。BACKGROUND事件模型也与发布事件在同一线程执行。ASYNC则在一个名叫pool-1-thread-1的新线程中执行。MAIN还是在UI线程中执行。

3.黏性事件

黏性事件和我们的粘性广播很类似,就是在发送事件之后再订阅该事件也能收到该事件。

用法

(1)注册粘性事件
EventBus.getDefault().register(MainActivity.this);
  • 1
(2)处理粘性事件
@Subscribe(sticky = true)
public void XXX(MessageEvent messageEvent) {
    ......
}
  • 1
  • 2
  • 3
  • 4
(3)发送粘性事件
EventBus.getDefault().postSticky(new MessageEvent("message"));
  • 1
(4)解除粘性事件
EventBus.getDefault().unregister(MainActivity.this);
  • 1

示例:

"/ 
当点击Post Message按钮发送粘性消息,此时因为没有注册事件所以并没有收到任何东西,当点击Regist EventBus按钮进行注册时就会收到之前发送的粘性消息,并且此时我们每次点击发送都会收到消息,当我们点击解除注册Unregist EventBus按钮的时候,再次点击Post Message也不会收到任何消息了。

代码:

public class MainActivity extends AppCompatActivity {

    private Button post_btn, regist_btn, unregist_btn;
    private int index = 0;

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

        post_btn = (Button) findViewById(R.id.post_message);
        regist_btn = (Button) findViewById(R.id.regist_seventbus);
        unregist_btn = (Button) findViewById(R.id.unregist_seventbus);

        post_btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                EventBus.getDefault().postSticky(new MessageEvent("message" +
                        "---" +index++));
            }
        });

        regist_btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                EventBus.getDefault().register(MainActivity.this);
            }
        });

        unregist_btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                EventBus.getDefault().unregister(MainActivity.this);
            }
        });


    }


    @Subscribe(threadMode = ThreadMode.POSTING, sticky = true)
    public void showMessagePOSTINGEvent(MessageEvent messageEvent){
        Log.d("POSTING",messageEvent.getMessage());
    }

    @Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
    public void showMessageMainEvent(MessageEvent messageEvent){
        Log.d("MAIN",messageEvent.getMessage());
    }

    @Subscribe(threadMode = ThreadMode.BACKGROUND, sticky = true)
    public void showMessageBACKGROUNDEvent(MessageEvent messageEvent){
        Log.d("BACKGROUND",messageEvent.getMessage());
    }

    @Subscribe(threadMode = ThreadMode.ASYNC, sticky = true)
    public void showMessageASYNCEvent(MessageEvent messageEvent){
        Log.d("ASYNC",messageEvent.getMessage());
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61

粘性事件就是这样可以收到注册之前发送的消息,但是它只能收到最新的一次消息,比如说在未注册之前已经发送了多条黏性消息了,然后再注册只能收到最近的一条消息。我们多次点击发送消息之后点击注册来看一下Log。

D/MAIN: message---12
D/POSTING: message---12
D/BACKGROUND: message---12
D/ASYNC: message---12
  • 1
  • 2
  • 3
  • 4

可以看到我们只收到了最后一次点击发送的消息。

尾语

学习到最后发现EventBus其实并不难,和我们之前用的广播很类似,同样需要注册和解除注册,处理消息的方法就类似于广播接收者的onReceive(),同样也可以选择粘性性质。

参考资料

http://www.jianshu.com/p/da9e193e8b03 

http://blog.csdn.net/harvic880925/article/details/40660137

分享到:
评论

相关推荐

    《EventBus使用详解(二)——EventBus使用进阶》对应源码

    博客《EventBus使用详解(二)——EventBus使用进阶》对应源码,博客地址:http://blog.csdn.net/harvic880925/article/details/40787203

    博客《 EventBus使用详解(一)——初步使用EventBus》对应源码

    博客《 EventBus使用详解(一)——初步使用EventBus》对应源码,博客地址:http://blog.csdn.net/harvic880925/article/details/40660137

    《EventBus使用详解(一)——初步使用EventBus》对应源码

    博客《EventBus使用详解(一)——EventBus使用进阶》对应源码,博客地址:http://blog.csdn.net/wangyi891223/article/details/49885999

    EventBus使用详解教程,带你学习eventbus。详解Demo

    本教程将深入讲解 EventBus 的使用方法,并通过一个名为 DavidEventBusDemo 的示例项目进行演示。 首先,理解 EventBus 的基本概念是至关重要的。EventBus 使用发布/订阅模式来传递事件。发布者(Publishers)发布...

    EventBus 使用详解

    EventBus 使用详解,EventBus是一款针对Android优化的发布/订阅事件总线 CSDN 地址:https://blog.csdn.net/yoyo_0316/article/details/52319554

    Android eventbus使用demo

    **Android EventBus 使用详解** EventBus 是 Android 开发中一个轻量级的消息发布/订阅库,由 GreenRobot 团队开发。它简化了组件间的通信,避免了过于复杂的回调和使用 Intent 进行 Activity、Fragment 之间的事件...

    EventBus源码详解(一):基本使用 Demo

    在本文中,我们将深入探讨 EventBus 的基本使用,并通过一个实际的 Demo 演示如何在两个 Fragment 之间优雅地传递消息。 ### EventBus 的核心概念 1. **事件(Event)**: 在 EventBus 中,事件是用于传递数据的对象...

    EventBus详解示例Demo

    **EventBus详解** EventBus是一款轻量级的事件总线库,它简化了Android应用中的组件间通信。在传统的Android开发中,我们通常使用接口回调、BroadcastReceiver或静态内部类来实现组件间的通信,但这些方式往往使得...

    Android之EventBus1.0 和EventBus3.0的使用详解

    主要是通信组件EventBus,EventBus是一款针对Android优化的发布/订阅事件总线。 博客地址:http://blog.csdn.net/dickyqie/article/details/55101035

    EventBus使用教程Demo

    **EventBus 使用教程详解** EventBus 是一个 Android 开发中常用的发布/订阅事件总线库,它简化了组件之间的通信,使得组件间解耦。在本文中,我们将深入探讨 EventBus 的核心概念、安装、基本使用、高级用法以及...

    AndroidEventBus框架的使用demo

    **Android EventBus 框架详解及使用示例** EventBus 是 Android 开发中广泛使用的轻量级事件总线框架,由 GreenRobot 团队开发。它简化了组件间的通信,使得在 Activity、Fragment、Service 之间传递消息变得...

    Android中EventBus的使用

    **Android中的EventBus详解** EventBus是一款非常流行的发布/订阅事件总线库,它简化了Android应用程序中的组件间通信,特别是在处理跨层级、跨组件交互时。与传统的使用Intent或回调函数相比,EventBus提供了更加...

    EventBusDemo

    【EventBus 框架详解】 EventBus 是一个 Android 应用程序开发中的轻量级事件总线库,它简化了组件之间的通信,使得不同组件(Activity、Fragment、Service 等)之间的交互变得更加简单和高效。这个"EventBusDemo...

    EventBus范例

    **EventBus范例详解** EventBus 是一个发布/订阅事件总线库,广泛应用于Android开发中,用于简化组件之间的通信。传统的Android组件间通信通常依赖于接口回调、BroadcastReceiver或直接引用,但这些方法在复杂性、...

    Android 消息分发使用EventBus的实例详解

    Android 消息分发使用EventBus的实例详解 1. AndroidStudio使用 dependencies { //最新版本 compile 'org.greenrobot:eventbus:3.0.0' //可以翻倍提高EventBus使用效率 provided 'de.greenrobot:eventbus-...

    otto_eventbus_demo

    【Otto EventBus 框架详解】 Otto EventBus 是 Google 的 Square 团队开发的一款轻量级事件总线库,它极大地简化了 Android 应用中的组件间通信。本项目"otto_eventbus_demo"旨在展示如何使用 Otto 实现组件间的...

    EventBus封装使用

    **EventBus封装使用详解** EventBus 是一个发布/订阅事件总线库,广泛应用于Android开发中,用于替代传统的BroadcastReceiver,实现组件间的通信。它的核心思想是解耦,使得发送事件和接收事件的组件之间无需直接...

    android事件总线EventBus3.0使用方法详解

    Android 事件总线 EventBus 3.0 使用方法详解 EventBus 3.0 是一个 Android 事件总线库,提供了一个灵活的事件处理机制,允许在应用程序中发布和订阅事件。下面将详细介绍 EventBus 3.0 的使用方法和原理。 ...

    详解vue 组件之间使用eventbus传值

    对于前端的我们而言,并非是只有写界面才是最大的问题,很多的情况下,我们需要关注的是数据,比如js页面的数据传递等等,学习vue我们也是需要知道怎么去使用数据 当然,使用存储也是可以得,但是并非一定要缓存,...

Global site tag (gtag.js) - Google Analytics