最近用Kotlin寫代碼比較多剖煌,寫的多了真的越來越來喜歡這門語言赋访。作為一門現(xiàn)代化的語言,Kotlin對(duì)比Java提供了簡介的語法啄枕,更強(qiáng)大的lambda支持婚陪,屬性擴(kuò)展委托等。作為一個(gè)Android開發(fā)者的我來言频祝,Kotlin over Java泌参。
組件之間的通信經(jīng)常用到,用傳統(tǒng)的接口方式也比較繁瑣智润。而且目前的項(xiàng)目基本也都使用了RxJava及舍,所以索性寫個(gè)RxBus來實(shí)現(xiàn)好了】弑粒可能有人會(huì)說锯玛,我直接用EventBus好了呀,github上一萬多個(gè)Star呢兼蜈!
我想說攘残,你喜歡就好。EventBus確實(shí)更加完整为狸,但是如果有現(xiàn)成的我個(gè)人是不喜歡用第三方的歼郭。
1.實(shí)現(xiàn)RxBus
object RxBus {
private val TAG = javaClass.simpleName
/**
* 用于保存RxBus事件的所有訂閱,并在需要時(shí)正確的取消訂閱辐棒。
*/
private val disposablesMap: HashMap<Any, CompositeDisposable?> by lazy {
HashMap<Any, CompositeDisposable?>()
}
/**
* 避免直接使用此屬性病曾,因?yàn)樗鼉H在內(nèi)聯(lián)函數(shù)中使用而暴露
*/
val rxBus = ReplaySubject.create<Any>().toSerialized()
/**
* 向RxBus發(fā)送一個(gè)事件牍蜂,這個(gè)事件可以來自任意一個(gè)線程
*/
fun send(event: Any) {
rxBus.onNext(event)
}
/**
* 訂閱特定類型T的事件√┩浚可以從任何線程調(diào)用
*/
inline fun <reified T : Any> observe(): Observable<T> {
return rxBus.ofType(T::class.java)
}
/**
* 從RxBus事件中取消注冊訂閱者
* 調(diào)用訂閱的取消訂閱方法
*/
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
}
}
/**
* 注冊訂閱以便以后正確注銷它以避免內(nèi)存泄漏
* @param disposable 擁有此訂閱的訂閱對(duì)象
*/
fun Disposable.registerInBus(disposable: Any) {
RxBus.register(disposable, this)
}
是的鲫竞,您沒有看錯(cuò)。這樣就實(shí)現(xiàn)了一個(gè)RxBus逼蒙,主要還是在disposable
上動(dòng)手腳从绘。
我們用CompositeDisposable
來管理disposable
。用HashMap
保存事件所有的訂閱是牢,當(dāng)RxBus發(fā)送事件時(shí)僵井,CompositeDisposable
會(huì)把disposable
添加到容器中,在接收事件的地方進(jìn)行訂閱處理邏輯驳棱。當(dāng)不再需要的時(shí)候批什,CompositeDisposable
就會(huì)調(diào)用clear()方法清除所有訂閱,防止內(nèi)存泄露社搅。
這么講可能有點(diǎn)含糊渊季,沒關(guān)系下面我寫個(gè)實(shí)例就很容易理解了。
2.RxBus實(shí)例
1)新建一個(gè)事件Event類
當(dāng)然我這里是為了規(guī)范便于理解起見罚渐,所以一律以xxxEvent
的方式命名
class UserEvent(var user: User)
data class User(var name: String, var age: Int)
在構(gòu)造里只寫了個(gè)簡單的User實(shí)體類,具體可以結(jié)合業(yè)務(wù)做改變
2)發(fā)送事件
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
對(duì)象后面帶個(gè)?是Kotlin的預(yù)判空指針特性青扔,可以提前提醒開發(fā)者預(yù)防空指針源织,可以說是十分貼心。
4)解除注冊
注意最后不要忘了微猖,在Activity/Fragment的onDestroy()中解除注冊,防止內(nèi)存泄露
override fun onDestroy() {
super.onDestroy()
RxBus.unRegister(this)
}
怕大家一遍不過癮谈息,所以再來一個(gè)發(fā)送List事件的例子:TwoActivity回發(fā)事件給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地址看。
最后附上效果演示圖
項(xiàng)目地址
https://github.com/weibindev/Kotlin_RxBus