前言
EventBus到了3.0版本,使用Apt注解處理器來(lái)在編譯期通過(guò)讀取@Subscribe()注解并解析生成java類來(lái)保存訂閱者關(guān)于的信息,比在之前使用反射來(lái)獲得這些訂閱者的信息速度要快屿聋。但是事件觸發(fā)依然是使用method.invoke來(lái)調(diào)用征字“鑫縱觀EventBus的源碼刑枝,還是有大量使用反射的地方。
然而惧辈,盡管反射非常強(qiáng)大,但也不能隨意大量使用。如果一個(gè)功能可以不用反射完成凑懂,那么最好就不用。由于反射允許代碼執(zhí)行一些在正常情況下不被允許的操作(比如訪問(wèn)私有的屬性和方法)梧宫,所以使用反射可能會(huì)導(dǎo)致意料之外的副作用接谨,使用反射相對(duì)來(lái)說(shuō)不安全 --代碼有功能上的錯(cuò)誤,降低可移植性塘匣。反射代碼破壞了類的封裝性抽象性脓豪,因此當(dāng)平臺(tái)發(fā)生改變的時(shí)候,代碼的行為就有可能也隨著變化忌卤。而且使用反射的性能較低扫夜。
反射這個(gè)異教徒,并不屬于OOP的范疇驰徊,簡(jiǎn)直就是代碼界的IS笤闯,強(qiáng)行蹂躪對(duì)象,破壞原有結(jié)構(gòu)棍厂,對(duì)面向?qū)ο蟮氖澜缬^進(jìn)行殘(危)酷(言)肢(聳)解(聽(tīng))颗味。好了,進(jìn)入正題:
我眼中EventBus的缺點(diǎn):
一牺弹,不夠簡(jiǎn)潔:需要手寫(xiě)大量register和unregister的垃圾代碼浦马,這對(duì)我來(lái)說(shuō)是致命的缺點(diǎn)
二时呀、不夠高效:雖然用了Apt和METHOD_CACHE來(lái)優(yōu)化了反射,單仍然不夠完美理想化
三捐韩、不夠?qū)Wⅲ菏录鬟f的框架退唠,就不需要關(guān)心線程切換什么的吧,你這么牛逼RxJava知道嗎
好了荤胁,話不多說(shuō)瞧预,開(kāi)車。
先看效果:
對(duì)仅政,沒(méi)錯(cuò)垢油,觸發(fā)事件一句代碼:
OkBus.getInstance().onEvent(EventTags.JUMP_TO_MAIN, null);
接收事件一句代碼
@Bus(tag = EventTags.JUMP_TO_MAIN)
支持粘連事件(先觸發(fā)后注冊(cè))
OkBus.getInstance().onStickyEvent(EventTags.FLASH_INIT_UI, null);
什么?注冊(cè)和反注冊(cè)圆丹?這些代碼全部都是插件自動(dòng)生成滩愁,不用再手動(dòng)寫(xiě)啦!
Javassist在編譯期間通過(guò)插件辫封,已經(jīng)幫你自動(dòng)生成注冊(cè)硝枉、反注冊(cè)、事件分發(fā)的代碼并且?guī)湍慵由侠簿胛ⅲ∪绻麤](méi)有這樣的方法妻味,會(huì)自動(dòng)生成并加上,如果本來(lái)就有欣福,就更簡(jiǎn)單了责球,直接在方法里面追加就可以了。
來(lái)看build/intermediates/transforms下的源代碼
Activity(Fragment)有onCreate(onActivityCreated)拓劝,onDestroy可以自動(dòng)加雏逾,想在別的地方用怎么辦?
請(qǐng)看Presenter中用法:
即使沒(méi)有那樣的時(shí)機(jī)讓插件自動(dòng)插入郑临,那只要吱個(gè)聲(加個(gè)注解)栖博,插件也會(huì)自己自動(dòng)幫你加。
添加后的代碼:
需要在哪個(gè)方法里注冊(cè)就加上@BusRegister注解厢洞,反注冊(cè)就加@BusUnRegister仇让,現(xiàn)在你可以在任何地方使用了。
那要是忘加注解了怎么辦犀变?
別急妹孙,插件依然會(huì)在編譯期間提醒你:
所有一切都是編譯期間所做的秋柄,零反射零代理获枝。實(shí)現(xiàn)的方式,不過(guò)一類骇笔,一插件省店,一注解嚣崭,百余行代碼而已。
1懦傍、OkBus類
OkBus屬性:
主要就是基本信息的存儲(chǔ)和單例的實(shí)現(xiàn)
OkBus register方法:
注冊(cè)的時(shí)候放入回調(diào)列表雹舀,如果是粘連事件,注冊(cè)時(shí)就去已分發(fā)的粘連事件庫(kù)存去拿參數(shù)并觸發(fā)回調(diào)粗俱。
OkBus反注冊(cè)和觸發(fā)事件方法:
反注冊(cè)就直接remove回調(diào)说榆,觸發(fā)時(shí)分普通事件和粘連事件,粘連事件就存庫(kù)里備用
OK寸认,以上就是全部代碼签财。這里直接用回調(diào)實(shí)現(xiàn)事件通知,沒(méi)有什么復(fù)雜的邏輯偏塞,現(xiàn)在考慮的情況也比較簡(jiǎn)單
2唱蒸、插件代碼
剩下的都是插件代碼:
BusInfo類:
存儲(chǔ)事件的相關(guān)的信息,便于生成代碼邏輯:
transform操作
然后在transform中灸叼,根據(jù)源代碼創(chuàng)建BusInfo神汹,處理BusInfo、利用BusHelper操作源代碼進(jìn)行方法和代碼的插入古今,
BusHelper生成代碼
BusHelper里面有一些模版代碼:
處理BusInfo:
獲取初始化OkBus方法的代碼
生成event事件分發(fā)的邏輯代碼
生成取消事件注冊(cè)的代碼
Ok沧卢,以上便是全部代碼蚁堤,百十行而已(Log占了一大部分),Gradle插件雖然是使用用groovy但狭,我真的完全沒(méi)看過(guò)任何博客學(xué)過(guò)groovy披诗,因?yàn)間roovy完全兼容java,閉著眼睛當(dāng)java寫(xiě)好像并沒(méi)有什么不對(duì)(不要噴我立磁,呈队,,)唱歧。
Javassist實(shí)現(xiàn)邏輯插入的部分宪摧,說(shuō)高深點(diǎn)叫操作修改字節(jié)碼,說(shuō)簡(jiǎn)單點(diǎn)就是字符串拼接颅崩,插入代碼或者方法几于。相比ASM,真的太適合java開(kāi)發(fā)者來(lái)使用了沿后。
以上代碼在T-MVP可以看到沿彭,TMVP本來(lái)想做成庫(kù),現(xiàn)在已經(jīng)徹底淪為實(shí)驗(yàn)室尖滚,歡迎各位客官前來(lái)把玩喉刘。
OK瞧柔,車已到站,下車請(qǐng)刷卡
QQ群:AndroidMVP 555343041
更新日志:
2017/1/31:AOP新增SysPermissionAspect支持動(dòng)態(tài)申請(qǐng)系統(tǒng)權(quán)限切片睦裳,輕松適配6.0+
2017/1/27:AOP新增DbRealmAspect支持Realm數(shù)據(jù)庫(kù)造锅,數(shù)據(jù)庫(kù)突破你想像的簡(jiǎn)單(年夜特供)
2017/1/8: 使用Apt封裝Retrofit生成ApiFactory替換掉所有的Repository,狂刪代碼
2017/1/7: 使用DataBinding替換掉所有的ButterKnife廉邑,狂刪代碼
2017/1/6: 使用DataBinding替換掉所有的ViewHolder哥蔚,狂刪代碼,從此邁向新時(shí)代
2016/12/30:使用Apt生成全局路由TRouter蛛蒙,更優(yōu)雅的頁(yè)面跳轉(zhuǎn)肺素,支持傳遞參數(shù)和共享view轉(zhuǎn)場(chǎng)動(dòng)畫(huà)
2016/12/29:去掉BaseMultiVH新增VHClassSelector支持更完美的多ViewHolder
2016/12/28:使用Apt生成全局的ApiFactory替代所有的Model
2016/12/27:增加了BaseMultiVH擴(kuò)展支持多類型的ViewHolder
2016/12/26:抽離CoreAdapterPresenter優(yōu)化TRecyclerView
安卓AOP實(shí)戰(zhàn):面向切片編程
Android實(shí)用技巧之:用好泛型,少寫(xiě)代碼
安卓AOP實(shí)戰(zhàn):APT打造極簡(jiǎn)路由
全局路由TRouter,更優(yōu)雅的頁(yè)面跳轉(zhuǎn)
安卓AOP實(shí)戰(zhàn):Javassist強(qiáng)擼EventBus
加入OkBus宇驾,實(shí)現(xiàn)注解傳遞事件
安卓AOP三劍客:APT,AspectJ,Javassist
1倍靡、去掉所有反射>2、新增apt初始化工廠课舍,替換掉了dagger2塌西。>3、新增aop切片筝尾,處理緩存和日志