前言:
我們知道rxjava+retrofit+mvp已經(jīng)出現(xiàn)很久了壁拉。由于最近項(xiàng)目需要大整改,故此封裝一個比較適用的框架豪直。首先網(wǎng)路框架暫時選用了最新的框架:rxjava+retrofit。至于mvp的話由于之前別人項(xiàng)目寫的太過雜亂又經(jīng)過多人之手,暫時無力修改试溯。當(dāng)然,封裝沒有絕對的好與壞郊酒,只有適不適合遇绞。每個公司有每個公司的規(guī)則。
參考了很多網(wǎng)上資料燎窘,最終整出了一套屬于自己的網(wǎng)絡(luò)框架摹闽。這里特別感謝csdn的大神 wzgiceman??
從這篇文獻(xiàn)中得到了自己的思路,因?yàn)槭褂胷etrofit的童鞋大多數(shù)都是使用了內(nèi)置的gson解析褐健,這樣有個問題:并不是每個公司的后臺都會乖乖地給你返回想要的 jsonObject付鹿。就比如我的后臺 result如果是集合則返回類似 {"result" :"[{xxx},{xxx}]"},如果是對象則返回 {"result":"{xxxxx}"這樣想都不用想,不處理直接使用的話肯定會報錯。所以修改 .addConverterFactory(GsonConverterFactory.create())-->.addConverterFactory(ScalarsConverterFactory.create()) 以string的數(shù)據(jù)返回舵匾。這里有人會問俊抵,這樣話不是更加不方便了嗎?明明人家都幫你解析好了你還多此一舉纽匙,而且可能只有你公司后臺是這樣返回的务蝠。
這里要說下:其實(shí)如果沒有這個框架,平常我們使用其他框架烛缔,比如xutils等等都是返回json字符串然后手動解析馏段,這樣有個好處:更加靈活,擴(kuò)展性更強(qiáng)践瓷。再舉個例子:我們的另一個項(xiàng)目返回的格式居然是 “{"status":"1"}”. 認(rèn)真看下它是一個字符串(不知道我們后臺腦子是不是抽了)院喜。這樣不用說同樣會報錯。其實(shí)這里這個例子是為了說明晕翠,我們不用使用內(nèi)置的gson解析喷舀,而是攔截得到的數(shù)據(jù)然后操作成我們想要的數(shù)據(jù)。換句話說淋肾,哪天你和你后臺吵架了硫麻,人家不幫你改那就尷尬了。
我們看下干貨:
封裝前:
首先我們可以看到?jīng)]有封裝的框架代碼很長樊卓,使用方法是配置okhttp拿愧,然后用observable去subscribe一個 subscriber ?緊接著就是四個回調(diào)。本人是很不喜歡這么多的回調(diào)碌尔,如果不用mvp模式編寫的話那么業(yè)務(wù)邏輯的代碼都要寫在activity中浇辜,而且這僅僅是一個接口,如果多個接口呢唾戚?
同時可以看到其實(shí)很多代碼是重復(fù)多余的柳洋。比如okhttp是配置。onCompleted叹坦、onStart這兩個回調(diào)在本人看來也是多余的熊镣。其實(shí)要用到的onNext(得到數(shù)據(jù)然后處理)、onError(錯誤的處理)募书。
接之前的話題绪囱,怎么才能將數(shù)據(jù)攔截靈活處理呢? 我們可以看到真正得到數(shù)據(jù)的是onNext 锐膜,而之前也說了毕箍,回調(diào)是在subscriber重寫的。那么我們的思路就來了:寫一個類繼承subscriber然后重寫onNext 道盏。得到的數(shù)據(jù)我們不就可以任意蹂躪了嗎而柑? 等到數(shù)據(jù)處理成自己想要的格式再用一個接口回調(diào)返回出去不就好了文捶?
順著這個思路我們寫一個ProgressSubscriber繼承Subscriber ?看到類名就想到了我們在訪問的同時加一個加載框。而回到中onStart可以做對話框顯示的初始化媒咳。 onComplete則消除對話框粹排。
而onNext則是真正的數(shù)據(jù)處理
再來看下那個接口
好了我們的Subscriber就寫好了。前文也說了 由于后臺的任性返回了不同的結(jié)構(gòu)涩澡。不過通過我們的處理之后不管之后返回什么結(jié)構(gòu)都可以解析顽耳,我們只要傳一個解析的實(shí)體類就可以了。真的很方便妙同。
接下來射富,我們重點(diǎn)用一個例子看看使用過程。
service有了粥帚,我們需要一個retrofit胰耗。而我把這些統(tǒng)一寫到一個工具類中
對象都有了之后只要做subscirbe的操作:
我們需要注冊一個 subscriber進(jìn)去。而之前我們已經(jīng)有了一個progressSubscriber 芒涡。同樣這個部分的操作我們都在HttpManager封裝柴灯。
基本的操作就好了
我們再看下activity 中具體的調(diào)用
這是我們的activity中的調(diào)用。 onNext中我們通過每個接口中不同的method去區(qū)分具體的接口费尽。然后做不同的操作赠群。兩個接口僅僅也是寫了這些代碼而已。
總結(jié):
其實(shí)我也是貼了部分重要代碼而已旱幼。做這個的目的還是為了能夠靈活處理返回的數(shù)據(jù)查描。主要的思路再說一遍:寫一個類繼承subscriber并重寫onNext 然后得到的數(shù)據(jù)我們再用一個接口回調(diào)。至于之后的那些封裝只是為了讓代碼更加簡潔而已速警,每個人有每個人的習(xí)慣和寫法叹誉,這里不做統(tǒng)一鸯两。
最后分享這個框架 接下去還會進(jìn)行改進(jìn)以及添加更多的工具:圖片處理框架 glide闷旧、數(shù)據(jù)庫框架dbflow等等。還是那句話:合適的才是好用的钧唐!
百度網(wǎng)盤 鏈接:http://pan.baidu.com/s/1dFKTDJj 密碼:9rk9
github :github.com/xmrkwzw/rxRetrofit-master
更新
2017/8/23 :嵌套接口的封裝
昨天一個小伙伴突然提了一個疑問:如果一個接口要在另一個接口請求結(jié)果的前提下完成(嵌套接口)那要怎么做忙灼?
我想都沒想
那不是可以在onnext里面做完繼續(xù)做嗎? 然后仔細(xì)想想 這個是針對單個接口的根據(jù)method的條件做if....else的判定钝侠。假設(shè)第一次請求是 BaseInfoApi.BASE_INFO_METHOD.然后第二次請求是BaseInfoApi.CIVILIZATION_METHOD那么第二次請求完就不會進(jìn)入第一個的條件了该园。所以導(dǎo)致第二個的回調(diào)沒法做。
那么有什么辦法可以做嵌套接口的開發(fā)呢帅韧? 答案是肯定的:我們知道rxjava有很多關(guān)鍵字里初,其中有一個是flatmap.剛好就是可以做接口的嵌套。
基于這個條件我們在baseApiInfo中又寫了一個方法
可以看到忽舟,我們先調(diào)用了 getBaseInfo的一個接口然后用flatmap關(guān)鍵字轉(zhuǎn)化成另一個observable 然后調(diào)用了getcivilization的接口双妨。這里需要注意的是func1里面的參數(shù)列表淮阐。上文我們也說過,我們不再用內(nèi)置的gson插件而是使用string的方式重新解析刁品。所以這里么的參數(shù)列表一定要和接口的service7一致
? ?public interfaceHttpApiService {
? ? ? ? ? ? ? @GET("brand/brandBaseInfo")
? ? ? ? ? ? ? ?ObservablegetBaseInfo(@Query("seqNum") String seqNum);
? ? ? ? ? ? ? ?@GET("brand/getMoralRateData")
? ? ? ? ? ? ? ?ObservablegetCivilization(@Query("classId") String classId);
? }
然后注冊下subscriber.此處我是直接注冊了progresssubscriber.這里有個bug暫不知道原因泣特。 ?第二個回調(diào)應(yīng)該和上面調(diào)用的httpRequest(observable);一樣。 這個方法進(jìn)去實(shí)際上做的也是同樣的操作挑随,但是不知道為什么回調(diào)的始終是第一個接口的結(jié)果状您,可是按道理第一個接口已經(jīng)在 flatmap轉(zhuǎn)換中的call方法回調(diào)了。所以這個問題還有待解決兜挨。但是總的來說 嵌套接口已經(jīng)用flatmap解決了膏孟,而且較之其他的方式,這個方式是最好的拌汇,代碼邏輯也是最合理的骆莹。
DBFlow
為什么使用DBFlow:綜合了 ActiveAndroid, Schematic, Ollie,Sprinkles 等庫的優(yōu)點(diǎn)。同時不是基于反射担猛,所以性能也是非常高幕垦,效率緊跟greenDAO其后「盗基于注解先改,使用apt技術(shù),在編譯過程中生成操作類蒸走,使用方式和ActiveAndroid高度相似仇奶,使用簡單。
特性:
無縫支持多個數(shù)據(jù)庫比驻;
使用annotation processing提高速度该溯;
ModelContainer類庫可以直接解析像JSON這樣的數(shù)據(jù);
增加靈活性的豐富接口别惦。
使用:
project build.gradle
app build.gradle
問題:
這里發(fā)現(xiàn)了一個問題狈茉,假如你的項(xiàng)目中使用了module 而如果將dbflow的依賴添加到 module的build.gradle中就會報初始化錯誤。所以建議將dbflow依賴寫在 app的build.gradle中
Api
使用dbflow的過程其實(shí)有遇到很多問題掸掸。最大的問題是假如你不翻墻氯庆,我們大天朝的百度幾乎都是復(fù)制來復(fù)制去的,沒有什么參考的意義扰付。本人在使用的過程遇到了問題通過 stackoverflow一步步查找最終找到了比較好的一個api
agrosner.gitbooks.io/dbflow/content/SQLiteWrapperLanguage.html
增:insert
插入的方式有
1 Model.insert()
如:dbflowModel.insert();
2 SQLite.insert()
3插入一個集合
除了上述方法 當(dāng)然也可以通過遍歷然后通過 model.insert();?? 但是如果數(shù)據(jù)量很大的情況下建議開啟事務(wù)
刪 delete
其中 使用 Delete.table(Table table)是清空表數(shù)據(jù)的作用
改 update
查 query
使用 SQLite.select().from(DBFlowModel.class).querySingle(); 查找一個對象
SQLite.select().from(DBFlowModel.class).queryList(); 查找一個集合對象
同樣還有以下api
事務(wù)
事務(wù)是一個數(shù)據(jù)必須具備的堤撵,如果保存10000條數(shù)據(jù),一條一條保存必然是很慢的羽莺,所以就需要用到事務(wù)实昨,批量保存。DBFlow的事務(wù)非常的強(qiáng)大盐固,同時使用也很復(fù)雜荒给;
查詢
保存
如果是新增表無需做特別的處理族跛,直接修改AppDatabase的版本號即可。
如果需要新增字段锐墙,除了需要修改AppDatabase的版本號外礁哄,還需要做特殊的處理,DBFlow的描述是:Migrations溪北。
例子:對People新增一個email字段
第1步桐绒,修改數(shù)據(jù)庫版本號
第2步,需要修改數(shù)據(jù)表對象結(jié)構(gòu)之拨,增加email
第3步茉继,執(zhí)行第二步之后,需要build(Android studio的build->Make?Project蚀乔、Mac的童鞋直接command+F9)烁竭,通過apt更新People_Table,接下來編寫Migrations
類名可以更加自己喜歡定義吉挣,我個人的規(guī)則是派撕,按照數(shù)據(jù)庫版本號和需要更新的數(shù)據(jù)表來命名,需要注意是:version = 2
數(shù)據(jù)庫升級就大功告成了睬魂。
基本的使用就這些终吼,其他api用法請往這邊看?https://agrosner.gitbooks.io/dbflow/content/SQLiteWrapperLanguage.html
Rxbus
它不是一個庫,而是一個文件氯哮,最短實(shí)現(xiàn)只有短短30行代碼际跪。RxBus本身不需要過多分析,它的強(qiáng)大完全來自于它基于的RxJava技術(shù)喉钢。響應(yīng)式編程(Reactive Programming)技術(shù)這幾年特別火姆打,RxJava是它在Java上的實(shí)作。RxJava天生就是類似sub/pub的觀察者模式肠虽,而且很容易處理線程切換
rxbus并沒有一個統(tǒng)一的標(biāo)準(zhǔn)幔戏,他是一種概念。如果要看概念的舔痕,網(wǎng)上也是有很多資料评抚。這里不做詳解
在用過rxjava前相信很多人使用過eventbus?
如果你的項(xiàng)目中已經(jīng)開始使用EventBus豹缀,沒有必要特意換用RxBus伯复。
如果你的項(xiàng)目計(jì)劃引入RxJava,并認(rèn)為統(tǒng)一風(fēng)格很重要邢笙,啟用RxBus啸如,拋棄EventBus沒有問題。但是請了解RxBus的問題氮惯,并關(guān)注RxBus的進(jìn)展叮雳,最好能用Rx的方式解決這個問題想暗。
使用:
推薦一個不錯的rxbus?github.com/xmrkwzw/Rxbus-1?如果只是做單獨(dú)的post發(fā)送消息網(wǎng)上有很多資源。而就發(fā)送粘性事件(stickyEvent) 我覺得這個封裝的很不錯帘不。
用法 :
訂閱者
發(fā)送者
glide
glide相信很多人都在用。而這次用到的是glide4.0 同時支持kotlin。
glide4.0在用法上和之前確實(shí)有不小的改變。新增的API(RequestBuilder,RequestOptions)
具體的用法可以到官網(wǎng)查看api?
或者查看某作者的整合博客
blog.csdn.net/github_33304260/article/details/72526237
這里只貼出部分功能的代碼
可以看出官方把有些方法都集成到了上述的兩個api中筛武。具體的其他方法請看官網(wǎng)介紹瞄摊。
以上框架就基本搭建好了,如有什么不足和bug田轧,歡迎提出意見和建議。