之所以寫這篇文章是最近我們自己的項目打算實現mvp模式的功能重構,而我們的項目數據接口全部是基于webservices接口實現的,查閱了下資料發現Rxjava+retrofit的框架不是一般的火,內心不免躁動起來,經過一天半的時間總結摸索出一個登陸的demo。整體框架是RXjava+retrofit+okhttp 的mvp模式。廢話不少了開始吧
開始之前就是小白一枚,準備工作如下:
1、什么是mvp
3、應該放在最后的之前寫的demo(包括單純webservices訪問;mvp模式的練習;rxjava練習)
先看看框架的樣子,上圖,包名對應的意思簡單解釋下
api:和明顯了在里邊放了一個登錄用的接口
convert:很重要,自定義的Retrofit convert,主要作用是自定義retrofit發送和接收的數據格式,特別是當前要發送的數據是xml格式,而我們返回的數據又要求截取其中的json要求
ksoap2,kxml2:這兩個包存儲了從ksoap的源碼中copy過來的源碼,目的是借用其中拼接xm,和請求頭的實現
model:模型
presenter:主要的邏輯代碼,控制view的顯示
view:也就是activity了
曰:授人以魚不如授人以漁
? ? 文章想從自己的問題解決思路出發,講講如何是實現webservices訪問的,首先不得不說一下我們之前拋棄所有的框架、思路僅僅借助ksoap2的jar包是如何實現webservices訪問的(相信看這篇文章的同學都是對webservices訪問有所了解的人,真是不明白的請自行度娘):
webservices是如何發送請求的
通過soapUI工具我們可以很清楚的看到,其本質就是將參數組裝在一個xml格式的數據中發送,發送和結果接收均是以xml的格式存在的,看看通過soapUI請求的格式就明白了:
ksoap2實現訪問webservices
看下訪問的關鍵代碼:
41-46將參數通過map的方式傳入
48-54查看源碼也就是組裝xml和請求頭的過程
56-64調用http的請求,發送接口請求
65-66獲取請求結果,當然查看源碼我們知道這個地方對返回的結果(原始的訪問返回為xml格式的)進行的解析
因為我們自己的接口返回的數據格式都是嚴格的json,所以最后的返回數據處理還包括
?SoapObject resultsRequestSOAP = (SoapObject)envelope.bodyIn;
Object obj = resultsRequestSOAP.getProperty(0);
String jsonStr = obj.toString();
來獲取json字符串
通過以上,就很明白了要想實現webservices的訪問無非就是(1)想辦法組裝xml(2)如何將返回xml中的json數據提取出來,結合我們現在要整合RXjava+retrofit+okhttp那么我們還需要考慮(自定義的convert)
RXjava-----mvp
1.添加需要依賴的庫
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'
//用來自定義的轉換器(關鍵詞:retrofit請求字符串,非json)
compile'com.squareup.retrofit2:converter-gson:2.1.0'
2、建立各個包,就像我在開頭貼出來的樣子,主要是為了mvp模式的調理準備的
3、采用ksoap中的源碼,我們不使用ksoap中網絡訪問的代碼,這部分代碼請自行裁剪,只保留其中的組拼裝xml部分。
我們在使用ksoap2的方法中,最后的數據調用使用的是HttpTransportSE.call(“”,enveloap),找到代碼中call方法,我們可以看到其中組裝xml的代碼
call方法的代碼量還時挺大的這里為了避免篇幅過長(已經很長了),就不在張貼,我們通過看其中的call方法我們發現
(1)包括了http的請求頭 beader
(2)包括了使用byte[] requestData = createRequestData(envelope,"UTF-8");將envelope轉成xml
(3)建立http的鏈接并發起請求
偶然發現一個地方,call方法在設置http請求的時候設置了connection.setRequestMethod("POST");post的請求方法,媽媽再也不用擔心我在定義api接口的時候糾結使用get還是post了。當然就算沒發現post也應該有意識明白使用post才對
4、翻過頭來繼續看看我們的目錄結構
創建api接口
public interfaceILoginApi {
@POST("/services/loginService")
rx.ObservableloginForMobile(@HeaderMapMap headerMap,@BodyString body);
}
毅然決然的使用了post,設置好url(請求的url都是拼接的,這個地方直接寫除baseurl以外的部分就可以了),登錄接口定義的參數需要設置請求的header,和請求的字符串(這里是組裝后的xml)
創建model
因為我們接口返回的數據統一json格式必包含{“message”:"","statuscode":200},所以創建一個基類BaseEnty作為其他實體的父類
public abstract classbaseEntity {
privateStringmessage;
privateStringstatuscode;
publicStringgetStatuscode() {returnstatuscode;}
public voidsetStatuscode(Stringstatuscode) {this.statuscode= statuscode;}
publicStringgetMessage() {returnmessage;}
public voidsetMessage(Stringmessage) {this.message= message;}
}
prestener接口
定義的很簡單就是在主頁面顯示登錄后返回的信息
public interfaceILoginPresenter {
voidlogin(Stringusername,Stringpwd);
}
view頁面省去不寫
這里描述下presenter的實現
soapHelpers是一個單例,里邊包含了傳輸參數后返回xml請求body和請求header的方法
至此調用api的方法就本應該可以實現網路的訪問了
loginApi.loginForMobile(soapHeaderMap,mBody)
.subscribeOn(Schedulers.io())
//指定回調在哪執行
.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());
}
});
細心的同學會發現,如果直接使用的是addConverterFactory(GsonConverterFactory.create())轉換器,那么一個問題是我們如何才能將返回的數據按照我們想要的格式返回呢??我們定義的api接口中返回的user對象怎么樣才能生效呢,我么返回的數據可是赤裸裸的xml啊!我們可什么也沒做呢。。。。。。細思極恐,抓緊查了下自定義retrofit 的convert,然后我們將自定義的轉換conver實現
數據的request按照教程直接寫就ok,思想就是保證我們的retrofit能夠發送自定義的字符串(也就是xml),重點是解析返回數據,得到我們想要的json
想到這里呦呦呦去看了一眼soap的源碼
SoapObject resultsRequestSOAP = (SoapObject)envelope.bodyIn;
Object obj = resultsRequestSOAP.getProperty(0);
String jsonStr = obj.toString();
最后將我們自定義的轉換器配置到retrofit中SoapConverterFactory.create()
retrofit=newRetrofit.Builder().baseUrl(baseUrl)
.addConverterFactory(SoapConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
運行ok
沒有忘記上源碼:https://github.com/sunfengqi8023/LoginForSoapAndRxjava
#### 歡迎訪問我的CSDN [熊貓卓Sun博客](http://blog.csdn.net/sfq19881224)