最近用Kotlin写代码比较多,写的多了真的越来越来喜欢这门语言。作为一门现代化的语言,Kotlin对比Java提供了简介的语法,更强大的lambda支持,属性扩展委托等。作为一个Android开发者的我来言,Kotlin over Java。
组件之间的通信经常用到,用传统的接口方式也比较繁琐。而且目前的项目基本也都使用了RxJava,所以索性写个RxBus来实现好了。可能有人会说,我直接用EventBus好了呀,github上一万多个Star呢!
沉默......
我想说,你喜欢就好。EventBus确实更加完整,但是如果有现成的我个人是不喜欢用第三方的。
1.实现RxBus
object RxBus {
private val TAG = javaClass.simpleName
/**
* 用于保存RxBus事件的所有订阅,并在需要时正确的取消订阅。
*/
private val disposablesMap: HashMap<Any, CompositeDisposable?> by lazy {
HashMap<Any, CompositeDisposable?>()
}
/**
* 避免直接使用此属性,因为它仅在内联函数中使用而暴露
*/
val rxBus = ReplaySubject.create<Any>().toSerialized()
/**
* 向RxBus发送一个事件,这个事件可以来自任意一个线程
*/
fun send(event: Any) {
rxBus.onNext(event)
}
/**
* 订阅特定类型T的事件。可以从任何线程调用
*/
inline fun <reified T : Any> observe(): Observable<T> {
return rxBus.ofType(T::class.java)
}
/**
* 从RxBus事件中取消注册订阅者
* 调用订阅的取消订阅方法
*/
fun unRegister(disposable: Any) {
val compositeDisposable = disposablesMap[disposable]
if (compositeDisposable == null) {
Log.w(TAG, "Trying to unregister subscriber that wasn't registered")
} else {
compositeDisposable.clear()
disposablesMap.remove(disposable)
}
}
/**
* internal修饰符 只有在相同模块中才能使用
*/
internal fun register(disposable: Any, composite: Disposable) {
var compositeDisposable = disposablesMap[disposable]
if (compositeDisposable == null) {
compositeDisposable = CompositeDisposable()
}
compositeDisposable.add(composite)
disposablesMap[disposable] = compositeDisposable
}
}
/**
* 注册订阅以便以后正确注销它以避免内存泄漏
* @param disposable 拥有此订阅的订阅对象
*/
fun Disposable.registerInBus(disposable: Any) {
RxBus.register(disposable, this)
}
是的,您没有看错。这样就实现了一个RxBus,主要还是在disposable
上动手脚。
我们用CompositeDisposable
来管理disposable
。用HashMap
保存事件所有的订阅,当RxBus发送事件时,CompositeDisposable
会把disposable
添加到容器中,在接收事件的地方进行订阅处理逻辑。当不再需要的时候,CompositeDisposable
就会调用clear()方法清除所有订阅,防止内存泄露。
这么讲可能有点含糊,没关系下面我写个实例就很容易理解了。
2.RxBus实例
1)新建一个事件Event类
当然我这里是为了规范便于理解起见,所以一律以xxxEvent
的方式命名
class UserEvent(var user: User)
data class User(var name: String, var age: Int)
在构造里只写了个简单的User实体类,具体可以结合业务做改变
2)发送事件
class OneActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_one)
initView()
initObserve()
}
private fun initView() {
val user = User("小明", 15)
mBtnActivity.setOnClickListener {
RxBus.send(UserEvent(user))
startActivity<TwoActivity>()
}
mBtnFragment.setOnClickListener {
startActivity<ThreeActivity>()
}
}
}
很简单,一行代码RxBus.send(UserEvent(user))
搞定
3)接收事件
class TwoActivity : AppCompatActivity() {
private lateinit var mUserList: MutableList<User>
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_two)
initObserve()
}
private fun initObserve() {
RxBus.observe<UserEvent>()
.subscribe { t: UserEvent? ->
kotlin.run {
mContent.text = "name:${t?.user?.name} age:${t?.user?.age}"
}
}
.registerInBus(this)
}
override fun onDestroy() {
super.onDestroy()
RxBus.unRegister(this)
}
}
在TwoActivity中接收事件来更新界面,t?.user?.name
对象后面带个?是Kotlin的预判空指针特性,可以提前提醒开发者预防空指针,可以说是十分贴心。
4)解除注册
注意最后不要忘了,在Activity/Fragment的onDestroy()中解除注册,防止内存泄露
override fun onDestroy() {
super.onDestroy()
RxBus.unRegister(this)
}
怕大家一遍不过瘾,所以再来一个发送List事件的例子:TwoActivity回发事件给OneActivity。代码比较简单,所以一并奉上了。
class UserListEvent(var users:MutableList<User>)
class TwoActivity : AppCompatActivity() {
private lateinit var mUserList: MutableList<User>
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_two)
initView()
initObserve()
}
private fun initView() {
mUserList = mutableListOf()
mUserList.add(User("小白", 11))
mUserList.add(User("小红", 12))
mUserList.add(User("小黑", 13))
mUserList.add(User("小绿", 14))
mBtnReturn.setOnClickListener {
RxBus.send(UserListEvent(mUserList))
finish()
}
}
private fun initObserve() {
RxBus.observe<UserEvent>()
.subscribe { t: UserEvent? ->
kotlin.run {
mContent.text = "name:${t?.user?.name} age:${t?.user?.age}"
}
}
.registerInBus(this)
}
override fun onDestroy() {
super.onDestroy()
RxBus.unRegister(this)
}
}
class OneActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_one)
initView()
initObserve()
}
private fun initView() {
val user = User("小明", 15)
mBtnActivity.setOnClickListener {
RxBus.send(UserEvent(user))
startActivity<TwoActivity>()
}
mBtnFragment.setOnClickListener {
startActivity<ThreeActivity>()
}
}
private fun initObserve() {
RxBus.observe<UserListEvent>()
.subscribe { t: UserListEvent? ->
kotlin.run {
mContent.text=t?.users?.toString()
}
}.registerInBus(this)
}
override fun onDestroy() {
super.onDestroy()
RxBus.unRegister(this)
}
}
还有Fragment之间的通信,代码也是大同小异的,所以和效果图一起展示了。具体的可以到文章末尾的github地址看。
最后附上效果演示图
项目地址
https://github.com/weibindev/Kotlin_RxBus
网友评论