Retrofit2+Rxjava2请求WebService(修订版)

前言

之前写了一篇文章 Retrofit2+Okhttp3+Rxjava通过SOAP协议请求WebService 通过整合Retrofit,Okhttp,Rxjava来实现WebService的网络访问,但其中还有许多地方不够完善,并没有发挥出Rxjava的强大之处,因此在这里通过完善封装,加入网络请求的取消,避免内存泄漏,使之更加简洁,方便使用。
这里只呈现出修改变动的部分,不太明白的话可以先看之前的文章。

依赖

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'

内容

1.ServiceStore请求接口
使用了Rxjava与Retrofit的适配器,因此,返回类型变为Observable<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请求管理者
移除execute()和doRequest()方法,对Retrofit进行初始化配置,ServiceStore的创建移到RequestManager初始化,这就意味着所有的请求接口都要写在ServiceStore内。

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;//管理者实例
    public OkHttpClient mClient;//OkHttpClient实例
    public ServiceStore mServiceStore;//请求接口
    private RequestManager() {
        init();
    }
    //单例模式,对提供管理者实例
    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类
该类实现Observer接口,对上游事件(请求结果)进行解析,然后通过自定义接口进行数据回调

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("请求发生未知错误");
                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.请求参数拼装

public class Node {
    //"<"节点转义
    private static String toStart(String name){
        return "<"+name+">";
    }
    //">"节点转义
    private static String toEnd(String name){
        return "</"+name+">";
    }
    //请求参数拼接
    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.请求示例
Rxjava2会返回一个 Disposable,它是观察者与被观察者之间的一个开关,调用它的dispose()方法,下游将不会收到发送事件,可以在页面销毁时调用,避免执行更新UI。
CompositeDisposable是Rxjava内置的一个容器,用于保存 Disposable,在页面销毁时候调用它的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.点击“网络请求”按钮,结果如图


请求结果
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,607评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,047评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,496评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,405评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,400评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,479评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,883评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,535评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,743评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,544评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,612评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,309评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,881评论 3 306
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,891评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,136评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,783评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,316评论 2 342

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,364评论 25 707
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,579评论 18 139
  • 1. 丝塔芙 日用洁面乳 Cetaphil Daily Skin Cleanser $7/240ml 起泡度:★★...
    太阳里的香肠猫阅读 5,515评论 0 6
  • 石梯处淡绿的小草, 用惺忪的睡醒偷瞄我。 长廊里微熏的小花, 用稚嫩的身姿仰视我。 他们的生命, 在袅袅的清风里新...
    256acdf50527阅读 327评论 0 0
  • 文|Sue She 朋友Y小姐电话QQ我,声嘶力竭、痛苦不堪。于是就知道了今日大半天的时间都奉献给她了。 幸福的感...
    天线鹿宝阅读 502评论 3 1