之所以寫這篇文章是最近我們自己的項(xiàng)目打算實(shí)現(xiàn)mvp模式的功能重構(gòu)聋溜,而我們的項(xiàng)目數(shù)據(jù)接口全部是基于webservices接口實(shí)現(xiàn)的,查閱了下資料發(fā)現(xiàn)Rxjava+retrofit的框架不是一般的火皮官,內(nèi)心不免躁動(dòng)起來(lái)脯倒,經(jīng)過(guò)一天半的時(shí)間總結(jié)摸索出一個(gè)登陸的demo。整體框架是RXjava+retrofit+okhttp 的mvp模式捺氢。廢話不少了開始吧
開始之前就是小白一枚藻丢,準(zhǔn)備工作如下:
1、什么是mvp
3悠反、應(yīng)該放在最后的之前寫的demo(包括單純webservices訪問(wèn);mvp模式的練習(xí);rxjava練習(xí))
先看看框架的樣子馍佑,上圖斋否,包名對(duì)應(yīng)的意思簡(jiǎn)單解釋下
api:和明顯了在里邊放了一個(gè)登錄用的接口
convert:很重要,自定義的Retrofit convert,主要作用是自定義retrofit發(fā)送和接收的數(shù)據(jù)格式拭荤,特別是當(dāng)前要發(fā)送的數(shù)據(jù)是xml格式茵臭,而我們返回的數(shù)據(jù)又要求截取其中的json要求
ksoap2,kxml2:這兩個(gè)包存儲(chǔ)了從ksoap的源碼中copy過(guò)來(lái)的源碼舅世,目的是借用其中拼接xm旦委,和請(qǐng)求頭的實(shí)現(xiàn)
model:模型
presenter:主要的邏輯代碼,控制view的顯示
view:也就是activity了
曰:授人以魚不如授人以漁
? ? 文章想從自己的問(wèn)題解決思路出發(fā)歇终,講講如何是實(shí)現(xiàn)webservices訪問(wèn)的社证,首先不得不說(shuō)一下我們之前拋棄所有的框架、思路僅僅借助ksoap2的jar包是如何實(shí)現(xiàn)webservices訪問(wèn)的(相信看這篇文章的同學(xué)都是對(duì)webservices訪問(wèn)有所了解的人评凝,真是不明白的請(qǐng)自行度娘):
webservices是如何發(fā)送請(qǐng)求的
通過(guò)soapUI工具我們可以很清楚的看到追葡,其本質(zhì)就是將參數(shù)組裝在一個(gè)xml格式的數(shù)據(jù)中發(fā)送,發(fā)送和結(jié)果接收均是以xml的格式存在的,看看通過(guò)soapUI請(qǐng)求的格式就明白了:
ksoap2實(shí)現(xiàn)訪問(wèn)webservices
看下訪問(wèn)的關(guān)鍵代碼:
41-46將參數(shù)通過(guò)map的方式傳入
48-54查看源碼也就是組裝xml和請(qǐng)求頭的過(guò)程
56-64調(diào)用http的請(qǐng)求宜肉,發(fā)送接口請(qǐng)求
65-66獲取請(qǐng)求結(jié)果匀钧,當(dāng)然查看源碼我們知道這個(gè)地方對(duì)返回的結(jié)果(原始的訪問(wèn)返回為xml格式的)進(jìn)行的解析
因?yàn)槲覀冏约旱慕涌诜祷氐臄?shù)據(jù)格式都是嚴(yán)格的json,所以最后的返回?cái)?shù)據(jù)處理還包括
?SoapObject resultsRequestSOAP = (SoapObject)envelope.bodyIn;
Object obj = resultsRequestSOAP.getProperty(0);
String jsonStr = obj.toString();
來(lái)獲取json字符串
注:掛上ksoap2訪問(wèn)webservices的demo
通過(guò)以上谬返,就很明白了要想實(shí)現(xiàn)webservices的訪問(wèn)無(wú)非就是(1)想辦法組裝xml(2)如何將返回xml中的json數(shù)據(jù)提取出來(lái)之斯,結(jié)合我們現(xiàn)在要整合RXjava+retrofit+okhttp那么我們還需要考慮(自定義的convert)
RXjava-----mvp
1.添加需要依賴的庫(kù)
compile'com.squareup.retrofit2:retrofit:2.1.0'
compile'com.squareup.okhttp3:okhttp:3.4.2'
compilegroup:'com.squareup.okhttp3',name:'okhttp-urlconnection',version:'3.3.0'
compile'com.squareup.retrofit2:converter-gson:2.1.0'
//適配器
compile'com.squareup.retrofit2:adapter-rxjava:2.1.0'
//RxJava
compile'io.reactivex:rxjava:1.1.6'
//RxAndroid
compile'io.reactivex:rxandroid:1.2.1'
//用來(lái)自定義的轉(zhuǎn)換器(關(guān)鍵詞:retrofit請(qǐng)求字符串,非json)
compile'com.squareup.retrofit2:converter-gson:2.1.0'
2遣铝、建立各個(gè)包佑刷,就像我在開頭貼出來(lái)的樣子,主要是為了mvp模式的調(diào)理準(zhǔn)備的
3酿炸、采用ksoap中的源碼瘫絮,我們不使用ksoap中網(wǎng)絡(luò)訪問(wèn)的代碼,這部分代碼請(qǐng)自行裁剪填硕,只保留其中的組拼裝xml部分麦萤。
我們?cè)谑褂胟soap2的方法中,最后的數(shù)據(jù)調(diào)用使用的是HttpTransportSE.call(“”扁眯,enveloap),找到代碼中call方法壮莹,我們可以看到其中組裝xml的代碼
call方法的代碼量還時(shí)挺大的這里為了避免篇幅過(guò)長(zhǎng)(已經(jīng)很長(zhǎng)了),就不在張貼姻檀,我們通過(guò)看其中的call方法我們發(fā)現(xiàn)
(1)包括了http的請(qǐng)求頭 beader
(2)包括了使用byte[] requestData = createRequestData(envelope,"UTF-8");將envelope轉(zhuǎn)成xml
(3)建立http的鏈接并發(fā)起請(qǐng)求
偶然發(fā)現(xiàn)一個(gè)地方命满,call方法在設(shè)置http請(qǐng)求的時(shí)候設(shè)置了connection.setRequestMethod("POST");post的請(qǐng)求方法,媽媽再也不用擔(dān)心我在定義api接口的時(shí)候糾結(jié)使用get還是post了施敢。當(dāng)然就算沒(méi)發(fā)現(xiàn)post也應(yīng)該有意識(shí)明白使用post才對(duì)
4周荐、翻過(guò)頭來(lái)繼續(xù)看看我們的目錄結(jié)構(gòu)
創(chuàng)建api接口
public interfaceILoginApi {
@POST("/services/loginService")
rx.ObservableloginForMobile(@HeaderMapMap headerMap,@BodyString body);
}
毅然決然的使用了post,設(shè)置好url(請(qǐng)求的url都是拼接的僵娃,這個(gè)地方直接寫除baseurl以外的部分就可以了)概作,登錄接口定義的參數(shù)需要設(shè)置請(qǐng)求的header,和請(qǐng)求的字符串(這里是組裝后的xml)
創(chuàng)建model
因?yàn)槲覀兘涌诜祷氐臄?shù)據(jù)統(tǒng)一json格式必包含{“message”:"","statuscode":200},所以創(chuàng)建一個(gè)基類BaseEnty作為其他實(shí)體的父類
public abstract classbaseEntity {
privateStringmessage;
privateStringstatuscode;
publicStringgetStatuscode() {returnstatuscode;}
public voidsetStatuscode(Stringstatuscode) {this.statuscode= statuscode;}
publicStringgetMessage() {returnmessage;}
public voidsetMessage(Stringmessage) {this.message= message;}
}
prestener接口
定義的很簡(jiǎn)單就是在主頁(yè)面顯示登錄后返回的信息
public interfaceILoginPresenter {
voidlogin(Stringusername,Stringpwd);
}
view頁(yè)面省去不寫
這里描述下presenter的實(shí)現(xiàn)
soapHelpers是一個(gè)單例默怨,里邊包含了傳輸參數(shù)后返回xml請(qǐng)求body和請(qǐng)求header的方法
至此調(diào)用api的方法就本應(yīng)該可以實(shí)現(xiàn)網(wǎng)路的訪問(wèn)了
loginApi.loginForMobile(soapHeaderMap,mBody)
.subscribeOn(Schedulers.io())
//指定回調(diào)在哪執(zhí)行
.observeOn(AndroidSchedulers.mainThread())
.subscribe(newAction1() {
@Override
public voidcall(User responseBody) {
String respone = responseBody.getMessage();
Log.v(TAG,"respone:"+ respone);
iLoginView.displayLoginMessage(respone);
}
}, newAction1() {
@Override
public voidcall(Throwable throwable) {
Log.v(TAG,"error:"+ throwable.toString());
}
});
細(xì)心的同學(xué)會(huì)發(fā)現(xiàn)讯榕,如果直接使用的是addConverterFactory(GsonConverterFactory.create())轉(zhuǎn)換器,那么一個(gè)問(wèn)題是我們?nèi)绾尾拍軐⒎祷氐臄?shù)據(jù)按照我們想要的格式返回呢匙睹?愚屁?我們定義的api接口中返回的user對(duì)象怎么樣才能生效呢,我么返回的數(shù)據(jù)可是赤裸裸的xml昂勖省霎槐!我們可什么也沒(méi)做呢。梦谜。丘跌。袭景。。闭树。細(xì)思極恐耸棒,抓緊查了下自定義retrofit 的convert,然后我們將自定義的轉(zhuǎn)換conver實(shí)現(xiàn)
數(shù)據(jù)的request按照教程直接寫就ok报辱,思想就是保證我們的retrofit能夠發(fā)送自定義的字符串(也就是xml)与殃,重點(diǎn)是解析返回?cái)?shù)據(jù),得到我們想要的json
想到這里呦呦呦去看了一眼soap的源碼
SoapObject resultsRequestSOAP = (SoapObject)envelope.bodyIn;
Object obj = resultsRequestSOAP.getProperty(0);
String jsonStr = obj.toString();
最后將我們自定義的轉(zhuǎn)換器配置到retrofit中SoapConverterFactory.create()
retrofit=newRetrofit.Builder().baseUrl(baseUrl)
.addConverterFactory(SoapConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
運(yùn)行ok
沒(méi)有忘記上源碼:https://github.com/sunfengqi8023/LoginForSoapAndRxjava
#### 歡迎訪問(wèn)我的CSDN [熊貓卓Sun博客](http://blog.csdn.net/sfq19881224)