前言
之前寫(xiě)了一篇文章 Retrofit2+Okhttp3+Rxjava通過(guò)SOAP協(xié)議請(qǐng)求WebService 通過(guò)整合Retrofit,Okhttp,Rxjava來(lái)實(shí)現(xiàn)WebService的網(wǎng)絡(luò)訪問(wèn),但其中還有許多地方不夠完善,并沒(méi)有發(fā)揮出Rxjava的強(qiáng)大之處,因此在這里通過(guò)完善封裝,加入網(wǎng)絡(luò)請(qǐng)求的取消,避免內(nèi)存泄漏,使之更加簡(jiǎn)潔,方便使用。
這里只呈現(xiàn)出修改變動(dòng)的部分,不太明白的話可以先看之前的文章。
依賴
Rxjava使用2.0的(之前使用1.0)
compile 'io.reactivex.rxjava2:rxjava:2.1.0'
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
新增Rxjava與Retrofit的適配器(Square官方提供的適配器目前僅支持Rxjava1)
compile 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0'
內(nèi)容
1.ServiceStore請(qǐng)求接口
使用了Rxjava與Retrofit的適配器,因此,返回類型變?yōu)镺bservable<ResponseBody>
public interface ServiceStore {
@Headers({
"Content-Type: text/xml; charset=utf-8",
"SOAPAction: http://tempuri.org/NewsInquiry"
})
@POST("WebServices/EhomeWebservice.asmx")
Observable<ResponseBody> getNews(@retrofit2.http.Body String str);
@GET
Observable<ResponseBody> download(@Url String fileUrl);
@GET("http://gank.io/api/data/{type}/{pageSize}/{pageIndex}")
Observable<ResultsEntity> getInfo(@Path("type") String type, @Path("pageSize") String pageSize, @Path("pageIndex") String pageIndex);
}
2.RequestManager請(qǐng)求管理者
移除execute()和doRequest()方法,對(duì)Retrofit進(jìn)行初始化配置,ServiceStore的創(chuàng)建移到RequestManager初始化,這就意味著所有的請(qǐng)求接口都要寫(xiě)在ServiceStore內(nèi)。
public class RequestManager {
public final static int CONNECT_TIMEOUT = 10;
public final static int READ_TIMEOUT = 20;
public final static int WRITE_TIMEOUT = 10;
public Retrofit mRetrofit;
private static RequestManager mRequestManager;//管理者實(shí)例
public OkHttpClient mClient;//OkHttpClient實(shí)例
public ServiceStore mServiceStore;//請(qǐng)求接口
private RequestManager() {
init();
}
//單例模式,對(duì)提供管理者實(shí)例
public static RequestManager getInstance() {
if (mRequestManager == null) {
synchronized (RequestManager.class) {
if (mRequestManager == null) {
mRequestManager = new RequestManager();
}
}
}
return mRequestManager;
}
private void init(){
Strategy strategy = new AnnotationStrategy();
Serializer serializer = new Persister(strategy);
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.readTimeout(READ_TIMEOUT, TimeUnit.SECONDS);
builder.writeTimeout(WRITE_TIMEOUT, TimeUnit.SECONDS);
builder.connectTimeout(CONNECT_TIMEOUT, TimeUnit.SECONDS);
builder.retryOnConnectionFailure(true);
mClient = builder.build();
mRetrofit = new Retrofit.Builder()
.baseUrl(Constans.WEBSERVICE_URL)
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(SimpleXmlConverterFactory.create(serializer))
.client(mClient)
.build();
mServiceStore=mRetrofit.create(ServiceStore.class);
}
public interface onRequestCallBack{
void onSuccess(String msg);
void onError(String msg);
}
}
3.新增ResultObserver類
該類實(shí)現(xiàn)Observer接口,對(duì)上游事件(請(qǐng)求結(jié)果)進(jìn)行解析,然后通過(guò)自定義接口進(jìn)行數(shù)據(jù)回調(diào)
public class ResultObserver implements Observer<ResponseBody> {
private RequestManager.onRequestCallBack callBack;
public ResultObserver( RequestManager.onRequestCallBack callBack){
this.callBack=callBack;
}
@Override
public void onSubscribe(@NonNull Disposable d) {
}
@Override
public void onNext(@NonNull ResponseBody responseBody) {
try {
String res = responseBody.string();
if (res == null) {
callBack.onError("請(qǐng)求發(fā)生未知錯(cuò)誤");
return;
}
if (res.contains("{") && res.contains("}")) {
int startIndex = res.indexOf("{");
int endIndex = res.lastIndexOf("}") + 1;
String json = res.substring(startIndex, endIndex);
callBack.onSuccess(json);
}
} catch (IOException e) {
e.printStackTrace();
callBack.onError(e.toString());
}
}
@Override
public void onError(@NonNull Throwable e) {
callBack.onError(e.toString());
}
@Override
public void onComplete() {
}
}
4.請(qǐng)求參數(shù)拼裝
public class Node {
//"<"節(jié)點(diǎn)轉(zhuǎn)義
private static String toStart(String name){
return "<"+name+">";
}
//">"節(jié)點(diǎn)轉(zhuǎn)義
private static String toEnd(String name){
return "</"+name+">";
}
//請(qǐng)求參數(shù)拼接
public static String getRequestParams(String namespace, Map<String,String> map){
if(map==null){
map=new HashMap<>();
}
StringBuffer sbf=new StringBuffer();
sbf.append(Node.toStart("Request"));
for(Map.Entry<String,String> entry:map.entrySet()){
sbf.append(Node.toStart(entry.getKey()));
sbf.append(entry.getValue());
sbf.append(Node.toEnd(entry.getKey()));
}
sbf.append(Node.toEnd("Request"));
String str="<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " +
"xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" " +
"xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n" +
" <soap:Header>\n" +
" <Identify xmlns=\"http://tempuri.org/\">\n" +
" <UserName>"+ Constans.USERNAME+"</UserName>\n" +
" <PassWord>"+Constans.PASSWORD+"</PassWord>\n" +
" </Identify>\n" +
" </soap:Header>\n" +
" <soap:Body>\n" +
" <"+namespace+" xmlns=\"http://tempuri.org/\">\n" +
" <str>"+sbf.toString()+"</str>\n" +
" </"+namespace+">\n" +
" </soap:Body>\n" +
"</soap:Envelope>";
return str;
}
}
5.請(qǐng)求示例
Rxjava2會(huì)返回一個(gè) Disposable,它是觀察者與被觀察者之間的一個(gè)開(kāi)關(guān),調(diào)用它的dispose()方法,下游將不會(huì)收到發(fā)送事件,可以在頁(yè)面銷毀時(shí)調(diào)用,避免執(zhí)行更新UI。
CompositeDisposable是Rxjava內(nèi)置的一個(gè)容器,用于保存 Disposable,在頁(yè)面銷毀時(shí)候調(diào)用它的clear方法即可
CompositeDisposable mCompositeDisposable= new CompositeDisposable();
private void getNews() {
Map<String,String> map=new HashMap<>();
map.put("PageSize",10+"");
map.put("PageIndex",1+"");
String request= Node.getRequestParams("NewsInquiry",map);
Disposable disposable = RequestManager.getInstance()
.mServiceStore
.getNews(request)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new ResultObserver(new RequestManager.onRequestCallBack() {
@Override
public void onSuccess(String msg) {
tv_msg.setText(msg);
}
@Override
public void onError(String msg) {
tv_msg.setText(msg);
}
}));
mCompositeDisposable.add(imageDisposable);
}
@Override
protected void onDestroy() {
super.onDestroy();
mCompositeDisposable.clear();
}
6.點(diǎn)擊“網(wǎng)絡(luò)請(qǐng)求”按鈕,結(jié)果如圖
