《Netkiller Android 手札》之 EventBus 使用详解

简介: Android EventBus 使用详解

本文节选自电子书《Netkiller Android 手札》


Netkiller Android 手札

http://www.netkiller.cn/android/index.html

Mr. Neo Chan, 陈景峯(BG7NYT)



中国广东省深圳市望海路半岛城邦三期
518067
+86 13113668890

<netkiller@msn.com>

$Id: book.xml 606 2013-05-29 09:52:58Z netkiller $

版权 © 2018 Neo Chan


版权声明

转载请与作者联系,转载时请务必标明文章原始出处和作者信息及本声明。

http://www.netkiller.cn
http://netkiller.github.io
http://netkiller.sourceforge.net
微信订阅号 netkiller-ebook (微信扫描二维码)
QQ:13721218 请注明“读者”
QQ群:128659835 请注明“读者”


2018-10

我的系列文档

编程语言

Netkiller Architect 手札 Netkiller Developer 手札 Netkiller Java 手札 Netkiller Spring 手札 Netkiller PHP 手札 Netkiller Python 手札
Netkiller Testing 手札 Netkiller Cryptography 手札 Netkiller Perl 手札 Netkiller Docbook 手札 Netkiller Project 手札 Netkiller Database 手札

第 47 章 EventBus

目录

47.1. 添加 EventBus 依赖到项目Gradle文件

47.2. 快速开始一个演示例子

47.2.1. 创建 MessageEvent 类

47.2.2. Layout

47.2.3. Activity

47.3. Sticky Events

47.3.1. MainActivity

47.3.2. StickyActivity

47.3.3. MessageEvent

47.3.4. 删除粘性事件

47.4. 线程模型

47.5. 配置 EventBus 

47.6. 事件优先级

47.7. 捕获异常事件

http://greenrobot.org/eventbus

在EventBus中主要有以下三个成员:

Event:事件,可以自定义为任意对象,类似Message类的作用;
Publisher:事件发布者,可以在任意线程、任意位置发布Event,已发布的Evnet则由EventBus进行分发;
Subscriber:事件订阅者,接收并处理事件,需要通过register(this)进行注册,而在类销毁时要使用unregister(this)方法解注册。每个Subscriber可以定义一个或多个事件处理方法,其方法名可以自定义,但需要添加@Subscribe的注解,并指明ThreadMode(不写默认为Posting)。

47.1. 添加 EventBus 依赖到项目Gradle文件

Gradle:

implementation 'org.greenrobot:eventbus:3.1.1'

完整的例子

apply plugin: 'com.android.application'

android {
    compileSdkVersion 28
    defaultConfig {
        applicationId "cn.netkiller.eventbus"
        minSdkVersion 26
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:28.0.0'
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
    implementation 'org.greenrobot:eventbus:3.1.1'
}

47.2. 快速开始一个演示例子

操作 EventBus 只需四个步骤

1. 注册事件

EventBus.getDefault().register( this );

2. 取消注册

EventBus.getDefault().unregister( this );

3. 订阅事件

	@Subscribe(threadMode = ThreadMode.MAIN)
    public void onMessageEvent(MessageEvent event) {
        Toast.makeText(this, event.message, Toast.LENGTH_SHORT).show();
    }

4. 发送数据

EventBus.getDefault().post(new MessageEvent("Helloworld"));

47.2.1. 创建 MessageEvent 类

package cn.netkiller.eventbus.pojo;

public class MessageEvent {
    public final String message;

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

47.2.2. Layout

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:layout_marginEnd="8dp"
        android:text="Button"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/textView" />

</android.support.constraint.ConstraintLayout>

47.2.3. Activity

package cn.netkiller.eventbus;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;

import cn.netkiller.eventbus.pojo.MessageEvent;

public class MainActivity extends AppCompatActivity {

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

        EventBus.getDefault().register(this);

        findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                EventBus.getDefault().post(new MessageEvent("Hello everyone!"));
            }
        });

    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        //取消注册 , 防止Activity内存泄漏
        EventBus.getDefault().unregister(this);
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onMessageEvent(MessageEvent event) {
        Toast.makeText(this, event.message, Toast.LENGTH_SHORT).show();
    }
}

47.3. Sticky Events

Sticky Events 粘性事件可以理解为Message做了持久化,直到Message被消费为止。无需注册即可发送Message。

下面的例子:在MainActivity发送事件,在StickyActivity里注册并且接收事件

A. MainActivity 发送事件:

EventBus.getDefault().postSticky(new MessageEvent("http://www.netkiller.cn"));

B. StickyActivity 接收事件 

1. 注册

EventBus.getDefault().register( this );

2. 事件接收

	@Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
    public void onMessageEvent(MessageEvent event) {
        Toast.makeText(this, event.message, Toast.LENGTH_SHORT).show();
    }

3. 取消注册

EventBus.getDefault().unregister( this ) ;

47.3.1. MainActivity

Layout

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:layout_marginEnd="8dp"
        android:text="Button"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/textView" />

</android.support.constraint.ConstraintLayout>

MainActivity

package cn.netkiller.eventbus;

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;

import cn.netkiller.eventbus.pojo.MessageEvent;

public class MainActivity extends AppCompatActivity {

    @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) {
                EventBus.getDefault().postSticky(new MessageEvent("Hello everyone!"));
                startActivity(new Intent(MainActivity.this, StickyActivity.class));
            }
        });

    }

}

47.3.2. StickyActivity

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".StickyActivity">

</android.support.constraint.ConstraintLayout>

StickyActivity

package cn.netkiller.eventbus;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.Toast;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;

import cn.netkiller.eventbus.pojo.MessageEvent;

public class StickyActivity extends AppCompatActivity {

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

        EventBus.getDefault().register(this);
    }

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

    @Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
    public void onMessageEvent(MessageEvent event) {
        Toast.makeText(this, event.message, Toast.LENGTH_SHORT).show();
    }

}

47.3.3. MessageEvent

package cn.netkiller.eventbus.pojo;

public class MessageEvent {
    public final String message;

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

47.3.4. 删除粘性事件

MessageEvent stickyEvent = EventBus.getDefault().getStickyEvent(MessageEvent.class);

// Better check that an event was actually posted before
if(stickyEvent != null) {
	// "Consume" the sticky event
	EventBus.getDefault().removeStickyEvent(stickyEvent);
	// Now do something with it
}

47.4. 线程模型

EventBus 有五种线程模型(ThreadMode) 

Posting:直接在事件发布者所在线程执行事件处理方法;
Main:直接在主线程中执行事件处理方法(即UI线程),如果发布事件的线程也是主线程,那么事件处理方法会直接被调用,并且未避免ANR,该方法应避免进行耗时操作;
MainOrdered:也是直接在主线程中执行事件处理方法,但与Main方式不同的是,不论发布者所在线程是不是主线程,发布的事件都会进入队列按事件串行顺序依次执行;
BACKGROUND:事件处理方法将在后台线程中被调用。如果发布事件的线程不是主线程,那么事件处理方法将直接在该线程中被调用。如果发布事件的线程是主线程,那么将使用一个单独的后台线程,该线程将按顺序发送所有的事件。
Async:不管发布者的线程是不是主线程,都会开启一个新的线程来执行事件处理方法。如果事件处理方法的执行需要一些时间,例如网络访问,那么就应该使用该模式。为避免触发大量的长时间运行的事件处理方法,EventBus使用了一个线程池来有效地重用已经完成调用订阅者方法的线程以限制并发线程的数量。  后面会通过代码展示五种ThreadMode的工作方式。
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".ThreadModeActivity">

    <Button
        android:id="@+id/buttonSend"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:layout_marginEnd="8dp"
        android:text="Send"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/buttonThread"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:layout_marginEnd="8dp"
        android:text="Send Thread"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/buttonSend" />
</android.support.constraint.ConstraintLayout>
package cn.netkiller.eventbus;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;

public class ThreadModeActivity extends AppCompatActivity {

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

        EventBus.getDefault().register(this);

        findViewById(R.id.buttonSend).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.d("EventBus Thread : ", Thread.currentThread().getName());
                EventBus.getDefault().post("http://www.netkiller.cn");
            }
        });

        findViewById(R.id.buttonThread).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        Log.d("EventBus Thread : ", Thread.currentThread().getName());
                        EventBus.getDefault().post("http://www.netkiller.cn");

                    }
                }).start();

            }
        });

    }

    @Subscribe(threadMode = ThreadMode.POSTING)
    public void onMessageEventPostThread(String event) {
        Log.d("EventBus PostThread", "Message: " + event + "  thread: " + Thread.currentThread().getName());
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onMessageEventMainThread(String event) {
        Log.d("EventBus MainThread", "Message: " + event + "  thread: " + Thread.currentThread().getName());
    }

    @Subscribe(threadMode = ThreadMode.MAIN_ORDERED)
    public void onEventMainOrdered(String event) {
        Log.d("EventBus MainOrdered", "Message: " + event + " thread:" + Thread.currentThread().getName());
    }

    @Subscribe(threadMode = ThreadMode.BACKGROUND)
    public void onMessageEventBackgroundThread(String event) {
        Log.d("EventBus BackgroundThread", "Message: " + event + "  thread: " + Thread.currentThread().getName());
    }

    @Subscribe(threadMode = ThreadMode.ASYNC)
    public void onMessageEventAsync(String event) {
        Log.d("EventBus Async", "Message: " + event + "  thread: " + Thread.currentThread().getName());
    }


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

在 main 线程中发布消息

D/EventBus Thread :: main
D/EventBus MainThread: Message: http://www.netkiller.cn  thread: main
D/EventBus PostThread: Message: http://www.netkiller.cn  thread: main
D/EventBus Async: Message: http://www.netkiller.cn  thread: pool-1-thread-1
D/EventBus BackgroundThread: Message: http://www.netkiller.cn  thread: pool-1-thread-2
D/EventBus MainOrdered: Message: http://www.netkiller.cn thread:main

在线程中发布消息

D/EventBus Thread :: Thread-2
D/EventBus BackgroundThread: Message: http://www.netkiller.cn  thread: Thread-2
D/EventBus PostThread: Message: http://www.netkiller.cn  thread: Thread-2
D/EventBus Async: Message: http://www.netkiller.cn  thread: pool-1-thread-2
D/EventBus MainOrdered: Message: http://www.netkiller.cn thread:main
D/EventBus MainThread: Message: http://www.netkiller.cn  thread: main

47.5. 配置 EventBus 

上面章节中的例子EventBus实例中采用默认方式

EventBus.getDefault().register(this);

这种方式的获取到的EventBus的都是默认属性,有时候并不能满足我们的要求,这时候我们可以通过EventBusBuilder来个性化配置EventBus的属性。

// 创建默认的EventBus对象,相当于EventBus.getDefault()。

EventBus installDefaultEventBus():
// 添加由EventBus“注释预处理器生成的索引
EventBuilder addIndex(SubscriberInfoIndex index):
// 默认情况下,EventBus认为事件类有层次结构(订户超类将被通知)
EventBuilder eventInheritance(boolean eventInheritance):
// 定义一个线程池用于处理后台线程和异步线程分发事件
EventBuilder executorService(java.util.concurrent.ExecutorService executorService):
// 设置忽略订阅索引,即使事件已被设置索引,默认为false
EventBuilder ignoreGeneratedIndex(boolean ignoreGeneratedIndex):
// 打印没有订阅消息,默认为true
EventBuilder logNoSubscriberMessages(boolean logNoSubscriberMessages):
// 打印订阅异常,默认true
EventBuilder logSubscriberExceptions(boolean logSubscriberExceptions):
// 设置发送的的事件在没有订阅者的情况时,EventBus是否保持静默,默认true
EventBuilder sendNoSubscriberEvent(boolean sendNoSubscriberEvent):
// 发送分发事件的异常,默认true
EventBuilder sendSubscriberExceptionEvent(boolean sendSubscriberExceptionEvent):
// 在3.0以前,接收处理事件的方法名以onEvent开头,方法名称验证避免不是以此开头,启用严格的方法验证(默认:false)
EventBuilder strictMethodVerification(java.lang.Class<?> clazz)
// 如果onEvent***方法出现异常,是否将此异常分发给订阅者(默认:false)
EventBuilder throwSubscriberException(boolean throwSubscriberException)

我的实例参考

EventBus eventBus = EventBus.builder().eventInheritance(true)
    .ignoreGeneratedIndex(false)
    .logNoSubscriberMessages(true)
    .logSubscriberExceptions(false)
    .sendNoSubscriberEvent(true)
    .sendSubscriberExceptionEvent(true)
    .throwSubscriberException(false)
    .strictMethodVerification(true)
    .build();
eventBus.register(this);

47.6. 事件优先级

priority 数值越大优先级又高

// MainActivity
	@Subscribe(priority = 2)
    public void onMessageEvent(MessageEvent event) {
        Toast.makeText(this, event.message, Toast.LENGTH_SHORT).show();
    }

	// SecondActivity
	@Subscribe(priority = 1)
    public void onMessageSecondEvent(MessageEvent event) {
        Toast.makeText(this, event.message, Toast.LENGTH_SHORT).show();
    }

时间拦截,MainActivity 收到信息后调用 EventBus.getDefault().cancelEventDelivery(event); 之后所有订阅将收不到信息。

// MainActivity
	@Subscribe(priority = 2)
    public void onMessageEvent(MessageEvent event) {
        Toast.makeText(this, event.message, Toast.LENGTH_SHORT).show();
        EventBus.getDefault().cancelEventDelivery(event);
    }

	// SecondActivity
	@Subscribe(priority = 1)
    public void onMessageSecondEvent(MessageEvent event) {
        Toast.makeText(this, event.message, Toast.LENGTH_SHORT).show();
    }

47.7. 捕获异常事件

在 init() 中加入你的业务逻辑,根据需要,在特定的情况下使用 throw new Exception("异常信息"); 抛出异常。异常会被 hrowableFailureEvent(ThrowableFailureEvent event) 捕获到。

package cn.netkiller.eventbus;

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Toast;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import org.greenrobot.eventbus.util.AsyncExecutor;
import org.greenrobot.eventbus.util.ThrowableFailureEvent;

import cn.netkiller.eventbus.pojo.MessageEvent;

public class MainActivity extends AppCompatActivity {

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

        EventBus.getDefault().register(this);

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

                AsyncExecutor.create().execute(
                        new AsyncExecutor.RunnableEx() {
                            @Override
                            public void run() throws Exception {
                                init();
                                EventBus.getDefault().post(new MessageEvent("Hello everyone!"));
                            }
                        }
                );
            }
        });
    }

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

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onMessageEvent(MessageEvent event) {
        Toast.makeText(this, event.message, Toast.LENGTH_SHORT).show();
    }

    public void init() throws Exception {
        // ...
        throw new Exception("实际发送异常");
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void hrowableFailureEvent(ThrowableFailureEvent event) {
        Log.d("EventBus", "hrowableFailureEvent: " + event.getThrowable().getMessage());
        Toast.makeText(this, event.getThrowable().getMessage(), Toast.LENGTH_SHORT).show();
    }

}

目录
相关文章
|
Java Android开发 Kotlin
Android | 这是一份详细的 EventBus 使用教程 | 牛气冲天新年征文
Android | 这是一份详细的 EventBus 使用教程 | 牛气冲天新年征文
840 0
Android | 这是一份详细的 EventBus 使用教程 | 牛气冲天新年征文
|
缓存 Java Android开发
Android EventBus的使用
Android EventBus的使用
|
Android开发
Android基础入门:EventBus实现总线数据分发
我们之前学习了Activity-》Activity中的数据传送,是通过intent.putExtra()方法实现的,如果要实现Activity-》Fragment或者Fragment-》Fragment都是不方便的,通过EventBus能很好的解决这个问题
204 0
|
调度 Android开发
【EventBus】发布-订阅模式 ( Android 中使用 发布-订阅模式 进行通信 )
【EventBus】发布-订阅模式 ( Android 中使用 发布-订阅模式 进行通信 )
356 0
【EventBus】发布-订阅模式 ( Android 中使用 发布-订阅模式 进行通信 )
|
Android开发
Android EventBus使用(不含源码解析)
官方文档:https://github.com/greenrobot/EventBus simplifies the communication between components decouples event senders and receiv...
1445 0
|
Android开发 Java 数据格式
Android项目实战(十三):浅谈EventBus
原文:Android项目实战(十三):浅谈EventBus 概述: EventBus是一款针对Android优化的发布/订阅事件总线。 主要功能是替代Intent,Handler,BroadCast在Fragment,Activity,Service。
1030 0
|
缓存 Java Android开发
Android——EventBus源码分析
停停走走又几天,断断续续这一年。时间还是如此之快,转眼间又到了17年的末尾了。趁着这些天还能静下心来看看代码,赶紧记录下自己的心得。 这一周,工作任务不多,总是想要看点什么但又不清楚该看啥,有些迷茫~不过既然自己还想要在Android路上继续前行,那么请深入探索吧! OK,闲话不多说。
741 0
|
Android开发
simple Android EventBus code
import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.
716 0
|
Android开发
Android应用开发—eventBus发布事件和事件处理的时序关系
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/voidreturn/article/details/78334378 占坑,简单说明下eventBus发布事件和事件处理的时序关系。
1311 0
下一篇
无影云桌面