Android笔记(八)事件总线之EventBus

本文介绍了EventBus的基本概念、三要素(事件、订阅者、发布者)、五种线程模型的使用,以及如何实现黏性事件。通过实例演示了如何在Activity、Fragment、Thread和Service间高效通信,以及如何利用EventBus提高代码可读性和解耦性。
摘要由CSDN通过智能技术生成

简介

 为了简化并且高效在ActivityFragmentThreadService等组件之间的通信,且进一步解耦,事件总线应运而生,我们简单介绍其中的EventBus

EventBus是一款针对安卓优化的发布-订阅事件总线。开销小,代码简洁,方便组件与线程、组件间的通信以及发送者与接受者解耦。比如说,Fragment之间的通信,要么需要Activity作为媒介,要么需要Broadcast作为媒介,效率不高,而且难以传递实体类数据。而EventBus就能很好解决这一问题

EventBus三要素

  • Event事件,可以是任意类型的对象。
  • Subscriber: 事件订阅者。在EventBus3.0之后,事件处理的方法可以随便取名,但是需要添加注解@Subscribe,并且需要指定线程模型(默认POSTING)。模型有五种 ,下面会说。
  • Pulisher: 事件发布者,可以在任意线程模型、位置发送事件,直接调用EventBus的post(Object)。根据post函数参数的类型,会自动调用订阅相应类型事件函数。(可以自己实例化EventBus对象,但一般使用EventBus.getDefault() 获得一个同步的DCL单例对象

五种线程模型

  • POSTING (默认):事件在那个线程发出来,就在那个线程运行。避免在此类型的事件中执行耗时操作,因为它会阻塞事件的传递,甚至会引起ANR。
  • MAIN : 事件处理会在UI线程中执行。不要执行耗时操作。
  • BACKGROUND:如果事件是在主线程发送的,事件处理函数会在新的线程中执行。如果是在子线程,则继用此线程,不新建。不要在函数内对UI进行操作。
  • ASYNC : 发布事件一律新建一个线程中执行,不要在函数内对UI进行操作。
  • MAIN_ORDERED: 在Android上,订阅者将在Android的主线程(UI线程)中被调用。与MAIN不同的是,事件将始终排队等待交付。这确保了post调用是非阻塞的。

使用方法

  1. 配置gradle:
implementation 'org.greenrobot:eventbus:3.3.1'
  1. 定义消息事件类:
data class Message(var msg : String = "")
  1. 注册和取消注册事件

class MainActivity : AppCompatActivity()
{
	override fun onCreate(savedInstanceState: Bundle?)
	{
		super.onCreate(savedInstanceState)

		val scrollView = ScrollView(this)
		with(LinearLayout(this))
		{
			orientation = LinearLayout.VERTICAL

			addView(Button(this@MainActivity).apply {
				text = "进入新界面"
				setOnClickListener {
					startActivity(Intent(this@MainActivity, SecondActivity::class.java))
				}
			})

			addView(Button(this@MainActivity).apply {
				text = "注册事件"
				setOnClickListener {
					// 注册事件
					EventBus.getDefault().register(this@MainActivity)
				}
			})

			scrollView.addView(this)
		}
		setContentView(scrollView)
	}

	override fun onDestroy()
	{
		super.onDestroy()
		// 取消注册事件
		EventBus.getDefault().unregister(this)
	}
}


  1. 事件订阅者处理事件
    MainActivity自定义方法处理事件,在这里将ThreadMode(线程模型)设置为MAIN,事件处理会在UI线程执行,用Toast展示:
@Subscribe(threadMode = ThreadMode.MAIN)
fun lexerEvent(message: Message)
{
	Toast.makeText(this, message.msg, Toast.LENGTH_LONG).show()
}
  1. 事件发布者发布事件
class SecondActivity : AppCompatActivity()
{
	override fun onCreate(savedInstanceState: Bundle?)
	{
		super.onCreate(savedInstanceState)
		setContentView(Button(this).apply { 
			text = "发送事件"
			setOnClickListener { 
				EventBus.getDefault().post(Message("Hello, This is a message!"))
				finish()
			}
		})
	}
}
  1. 使用方法也简单,先点击 “注册事件” ,在跳转到SecondActivity,点击“发送事件”,这样返回到MainActivity也就有Toast输出了。

EventBus 的黏性事件

 所谓黏性事件,就是发送事件后再订阅该事件也能收到该事件,这和黏性广播类似。
我们在MainActivity写一个方法处理:

@Subscribe(threadMode = ThreadMode.POSTING, sticky = true)
fun lexerStickyEvent(message: Message)
{
	Toast.makeText(this, message.msg, Toast.LENGTH_LONG).show()
}

 在SecondActivity加入按钮发送黏性事件,注意是postSticky

class SecondActivity : AppCompatActivity()
{
	override fun onCreate(savedInstanceState: Bundle?)
	{
		super.onCreate(savedInstanceState)
		setContentView(LinearLayout(this).apply {
			orientation = LinearLayout.VERTICAL

			addView(Button(this@SecondActivity).apply {
				text = "发送事件"
				setOnClickListener {
					EventBus.getDefault().post(Message("Hello, This is a message!"))
					finish()
				}
			})

			addView(Button(this@SecondActivity).apply {
				text = "发送黏性事件"
				setOnClickListener {
					EventBus.getDefault().postSticky(Message("Hello, This is a sticky message!"))
					finish()
				}
			})
		})
	}
}

 使用方法是,先进入SecondActivity,点击“发送黏性事件”,返回到MainActivity后,再点击“注册事件”就能成功显示。
 这是MainActivity的代码:

class MainActivity : AppCompatActivity()
{
	override fun onCreate(savedInstanceState: Bundle?)
	{
		super.onCreate(savedInstanceState)

		val scrollView = ScrollView(this)
		with(LinearLayout(this))
		{
			orientation = LinearLayout.VERTICAL

			addView(Button(this@MainActivity).apply {
				text = "进入新界面"
				setOnClickListener {
					startActivity(Intent(this@MainActivity, SecondActivity::class.java))
				}
			})

			addView(Button(this@MainActivity).apply {
				text = "注册事件"
				setOnClickListener {
					// 注册事件
					EventBus.getDefault().register(this@MainActivity)
				}
			})

			scrollView.addView(this)
		}
		setContentView(scrollView)
	}

	override fun onDestroy()
	{
		super.onDestroy()
		// 取消注册事件
		EventBus.getDefault().unregister(this)
	}

	@Subscribe(threadMode = ThreadMode.MAIN)
	fun lexerEvent(message: Message)
	{
		Toast.makeText(this, message.msg, Toast.LENGTH_LONG).show()
	}

	@Subscribe(threadMode = ThreadMode.POSTING, sticky = true)
	fun lexerStickyEvent(message: Message)
	{
		Toast.makeText(this, message.msg, Toast.LENGTH_LONG).show()
	}
}

data class Message(var msg : String = "")

小结

EventBus入门是非常容易的,这里不做过多介绍,有兴趣可以自行查阅源码,也可以看其他博主的详细解读。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值