Android RxJava+Retrofit统一处理API

假设有个登录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();    }}

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于Android项目中的网络请求,RxJavaRetrofit和MVP是常用的框架组合。下面是一个简单的网络框架封装示例: 首先,在项目中引入RxJavaRetrofit的依赖。 ``` implementation 'io.reactivex.rxjava2:rxjava:2.2.19' implementation 'io.reactivex.rxjava2:rxandroid:2.1.1' implementation 'com.squareup.retrofit2:retrofit:2.9.0' implementation 'com.squareup.retrofit2:converter-gson:2.9.0' implementation 'com.squareup.retrofit2:adapter-rxjava2:2.9.0' ``` 然后,创建一个Retrofit的单例类,用于进行网络请求的初始化和配置。 ```java public class RetrofitClient { private static Retrofit retrofit; private static final String BASE_URL = "https://api.example.com/"; public static Retrofit getClient() { if (retrofit == null) { retrofit = new Retrofit.Builder() .baseUrl(BASE_URL) .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .build(); } return retrofit; } } ``` 接下来,创建一个ApiService接口,定义网络请求的方法。 ```java public interface ApiService { @GET("users") Observable<List<User>> getUsers(); } ``` 然后,创建一个DataManager类,用于管理网络请求。 ```java public class DataManager { private ApiService apiService; public DataManager() { apiService = RetrofitClient.getClient().create(ApiService.class); } public Observable<List<User>> getUsers() { return apiService.getUsers(); } } ``` 最后,在MVP的Presenter中调用DataManager类进行网络请求。 ```java public class UserPresenter { private UserView userView; private DataManager dataManager; public UserPresenter(UserView userView) { this.userView = userView; dataManager = new DataManager(); } public void getUsers() { dataManager.getUsers() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Observer<List<User>>() { @Override public void onSubscribe(Disposable d) { // 在请求开始时的操作 } @Override public void onNext(List<User> users) { // 请求成功返回数据时的操作 userView.showUsers(users); } @Override public void onError(Throwable e) { // 请求失败时的操作 userView.showError(e.getMessage()); } @Override public void onComplete() { // 请求完成时的操作 } }); } } ``` 这样,就完成了一个简单的Android RxJava + Retrofit + MVP网络框架封装。你可以根据自己的需要,进行进一步的封装和扩展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值