美文网首页
Android RxJava+Retrofit统一处理API

Android RxJava+Retrofit统一处理API

作者: Jason_儿 | 来源:发表于2018-01-31 15:34 被阅读0次

    假设有个登录API,登录返回的值是

    {"code":0,msg:"登录成功","data":{"username":"xxx","nikename":"xxx"...}}

    {"code":-100,msg:"用户不存在","data":null}

    {"code":-101,msg:"密码错误","data":null}

    ...

    用其他框架Http请求的时候,比如默认回调是HttpCallback,我们一般会对这个HttpCallback加一层封装比如MyHttpCallback,在MyHttpCallback里面

    1) JSON转成Bean //也有很多框架自带Gson

    2) code<0的时候弹出一个Toast显示msg

    OkHttpUtils        .get()        .url("http://xxx")        .addParams("username","xxx")        .addParams("password","xxx")        .build()        .execute(newMyHttpCallback() {@OverridepublicvoidonError(Exception e){            }@OverridepublicvoidonFailure(intcode, String msg){            }@OverridepublicvoidonSuccess(intcode, String msg, User user){              }        });

    返回分为3种情况:

    第一种是连接服务端失败(比如常见的404、500、502等)

    第二种是请求成功但服务端告知我们参数有误

    第三种是完全正确的

    那使用RxJava+Retrofit该如何写出效果类似MyHttpCallback的功能呢?

    1) 一般第一反应就是在Subscriber的onNext里面去判断,这样的写法满足不了这样的需求:code<0的时候要Retry

    2) Retrofit我们都采用Gson处理返回的数据,如果我返回的结果比较简单,比如根据手机号返回一个验证码{"code":0,msg:"获取验证码成功","data":"8451"},还是要建立一个Bean类,有点麻烦,我想不写这个Bean类,在onNext传入的参数可不可以直接是JSONObject或者String

    3) 我们会经常在onNext里面去处理UI,那我们应该知道需要在Activity的onDestroy()取消订阅。第一想法就是在Activity声明一个全局变量

    privateCompositeSubscription compositeSubscription;

    每次订阅的时候都添加到compositeSubscription

    Subscription subscription = xxx

            .xxx()

            .retryWhen(xxx)

            .subscribeOn(Schedulers.io())

            .observeOn(AndroidSchedulers.mainThread()); 

            .subscribe(xxx);

    compositeSubscription.add(subscription);

    然后在onDestroy()里面

    compositeSubscription.unsubscribe();

    这样写法没什么问题,只是每次订阅都要重复这2句

    Subscription subscription = xxx;

    compositeSubscription.add(subscription);

    不是链式了,不好看。

    4) 我们的项目里应该有很多公共的部分

    .subscribeOn(Schedulers.io())

    .observeOn(AndroidSchedulers.mainThread());

    比如我的项目里这部分都是一样的,每个请求都写这么长一串也不太好看。

    直接上代码,看看最终的写法

    publicclassMainActivityextendsBaseActivityimplementsView.OnClickListener{@OverrideprotectedvoidonCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);    }@OverridepublicvoidonClick(View view){        DX168API.get()                .login("xxx","xxx")                .retryWhen(newRetryWhenNetworkException())//可以设置重试次数,延迟重试.compose(newDX168Transformer())//一些通用的处理,如subscribeOn和observeOn.lift(newBindActivityOperator(this))//绑定Activity,可以指定Activity的生命周期,用来取消订阅.subscribe(newDX168Subscriber(getApplicationContext()) {@OverridepublicvoidonSuccess(User user){//TODO}                });        DX168API.get()                .getRegisterVerifyCode("18888888888")                .retryWhen(newRetryWhenNetworkException())                .compose(newDX168Transformer())                .lift(newBindActivityOperator(this))                .subscribe(newDX168Subscriber(getApplicationContext()) {@OverridepublicvoidonSuccess(String data){//TODO// data就是verifyCode}                });    }}

    publicclassDX168GsonResponseBodyConverterimplementsConverter{privatefinalGson gson;privatefinalType type;    DX168GsonResponseBodyConverter(Gson gson, Type type) {this.gson = gson;this.type = type;    }@OverridepublicTconvert(ResponseBody responseBody)throwsIOException{        String value = responseBody.string();try{            JSONObject response =newJSONObject(value);intcode = response.optInt("code");            String msg = response.optString("msg");if(code == DX168API.RESULT_OK) {//如果返回结果是JSONObject或者DX168Response则无需经过Gsonif(type.toString().equals(JSONObject.class.toString())) {return(T) response;                }elseif(type.toString().equals(DX168Response.class.toString())) {                    Object data = response.opt("data");                    DX168Response dx168Response =newDX168Response(code, msg, data);return(T) dx168Response;                }else{returngson.fromJson(value, type);                }            }else{//返回的code不是RESULT_OK时Toast显示msgthrownewDX168Exception(code, msg, value);            }        }catch(JSONException e) {//服务端返回的不是JSON,服务端出问题thrownewDX168Exception(-1,"", value);        }    }}

    publicabstractclassDX168SubscriberextendsSubscriber{privateContext context;publicDX168Subscriber(Context applicationContext){this.context = applicationContext.getApplicationContext();    }@OverridepublicvoidonError(Throwable throwable){        Throwable e = throwable;while(throwable.getCause() !=null) {            e = throwable;            throwable = throwable.getCause();        }if(einstanceofConnectException || einstanceofSocketTimeoutException || einstanceofTimeoutException) {            onNetworkException(e);        }elseif(einstanceofDX168Exception) {            onDX168Exception((DX168Exception) e);        }else{            onUnknownException(e);        }    }@OverridepublicvoidonNext(DX168Response dx168Response){        Object data = dx168Response.getData();if(data == JSONObject.NULL) {            data =null;        }        onSuccess((T) data);    }publicabstractvoidonSuccess(T data);@OverridepublicvoidonCompleted(){    }publicvoidonDX168Exception(DX168Exception e){        Toast.makeText(context, e.getMessage(), Toast.LENGTH_SHORT).show();    }publicvoidonNetworkException(Throwable e){        Toast.makeText(context,"网络较慢,请稍候...", Toast.LENGTH_SHORT).show();    }publicvoidonUnknownException(Throwable e){        Toast.makeText(context, e.toString(), Toast.LENGTH_SHORT).show();    }}

    publicclassRetryWhenNetworkExceptionimplementsFunc1,Observable>{privateintcount =5;privatelongdelay =5000;privatelongincreaseDelay =5000;publicRetryWhenNetworkException(){    }publicRetryWhenNetworkException(intcount,longdelay){this.count = count;this.delay = delay;    }publicRetryWhenNetworkException(intcount,longdelay,longincreaseDelay){this.count = count;this.delay = delay;this.increaseDelay = increaseDelay;    }@OverridepublicObservable call(Observable observable) {returnobservable                .zipWith(Observable.range(1, count +1),newFunc2() {@OverridepublicWrappercall(Throwable throwable, Integer integer){returnnewWrapper(throwable, integer);                    }                }).flatMap(newFunc1>() {@OverridepublicObservable call(Wrapper wrapper) {if((wrapper.throwableinstanceofConnectException                                || wrapper.throwableinstanceofSocketTimeoutException                                || wrapper.throwableinstanceofTimeoutException)                                && wrapper.index < count +1) {//如果超出重试次数也抛出错误,否则默认是会进入onCompletedreturnObservable.timer(delay + (wrapper.index -1) * increaseDelay, TimeUnit.MILLISECONDS);                        }returnObservable.error(wrapper.throwable);                    }                });    }privateclassWrapper{privateintindex;privateThrowable throwable;publicWrapper(Throwable throwable,intindex){this.index = index;this.throwable = throwable;        }    }}

    publicclassBaseActivityextendsActivity{privateList subscribers;publicvoidaddSubscriber(Subscriber subscriber, ActivityLifecycle unsubscribeOn){if(subscribers ==null) {            subscribers =newArrayList<>();        }        subscribers.add(newSubscriberWrapper(subscriber, unsubscribeOn));    }privateclassSubscriberWrapper{        Subscriber subscriber;        ActivityLifecycle unsubscribeOn;publicSubscriberWrapper(Subscriber subscriber, ActivityLifecycle unsubscribeOn){this.subscriber = subscriber;this.unsubscribeOn = unsubscribeOn;        }    }@OverrideprotectedvoidonStop(){for(SubscriberWrapper wrapper : subscribers) {if(wrapper.unsubscribeOn == ActivityLifecycle.OnStop) {                wrapper.subscriber.unsubscribe();                subscribers.remove(wrapper);            }        }super.onStop();    }@OverrideprotectedvoidonDestroy(){for(SubscriberWrapper wrapper : subscribers) {if(wrapper.unsubscribeOn == ActivityLifecycle.OnDestroy) {                wrapper.subscriber.unsubscribe();                subscribers.remove(wrapper);            }        }super.onDestroy();    }}

    就这样吧,有兴趣的看看代码,不清楚的或者有不足的地方,欢迎交流。

    相关文章

      网友评论

          本文标题:Android RxJava+Retrofit统一处理API

          本文链接:https://www.haomeiwen.com/subject/fyakzxtx.html