网络请求一般会封装在Library的Module中,为了尽量简化网络请求的代码,使用Retrofit2结合RxJava2做了封装。
引入依赖
compile 'com.squareup.retrofit2:retrofit:2.2.0'
compile 'com.squareup.retrofit2:converter-gson:2.2.0'
compile 'com.squareup.retrofit2:adapter-rxjava2:2.2.0'
compile 'com.squareup.okhttp3:logging-interceptor:3.6.0'
compile 'io.reactivex.rxjava2:rxjava:2.0.8'
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
compile 'com.google.code.gson:gson:2.8.0'
compile 'org.greenrobot:eventbus:3.0.0'
在自定义的Application中定义BaseUrl、公共请求头、公共请求参数的抽象方法
/**
* 配置网络请求根路径
*/
public abstract String getBaseUrl();
/**
* 配置网络请求头
*/
public abstract ArrayMap<String, String> getRequestHeader();
/**
* 配置公共请求参数
*/
public abstract ArrayMap<String, String> getRequestParams();
定义静态属性
public class Constants {
public static final int NET_CODE_SUCCESS = 0;
public static final int NET_CODE_ERROR = 1;
public static final int NET_CODE_CONNECT = 400;
public static final int NET_CODE_UNKNOWN_HOST = 401;
public static final int NET_CODE_SOCKET_TIMEOUT = 402;
public static final String CONNECT_EXCEPTION = "网络连接异常,请检查您的网络状态";
public static final String SOCKET_TIMEOUT_EXCEPTION = "网络连接超时,请检查您的网络状态,稍后重试";
public static final String UNKNOWN_HOST_EXCEPTION = "网络异常,请检查您的网络状态";
}
定义统一的请求结果解析
public class Result<T> implements Serializable {
private int code;
private String msg;
private T data;
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
定义拦截器
获取自定义Application中返回的公共请求头
public class HeaderInterceptor implements Interceptor {
@Override public Response intercept(Chain chain) throws IOException {
Request originalRequest = chain.request();
ArrayMap<String, String> headers = BaseApp.getAppContext().getRequestHeader();
//如果公共请求头不为空,则构建新的请求
if (headers != null) {
Request.Builder requestBuilder = originalRequest.newBuilder();
for (String key : headers.keySet()) {
requestBuilder.addHeader(key, headers.get(key));
}
requestBuilder.method(originalRequest.method(), originalRequest.body());
return chain.proceed(requestBuilder.build());
}
return chain.proceed(originalRequest);
}
}
获取自定义Application中返回的公共请求参数
public class ParamsInterceptor implements Interceptor {
@Override public Response intercept(Chain chain) throws IOException {
Request oldRequest = chain.request();
ArrayMap<String, String> params = BaseApp.getAppContext().getRequestParams();
//如果公共请求参数不为空,则构建新的请求
if (params != null) {
Request.Builder newRequestBuilder = oldRequest.newBuilder();
//GET请求则使用HttpUrl.Builder来构建
if ("GET".equalsIgnoreCase(oldRequest.method())) {
HttpUrl.Builder httpUrlBuilder = oldRequest.url().newBuilder();
for (String key : params.keySet()) {
httpUrlBuilder.addQueryParameter(key, params.get(key));
}
newRequestBuilder.url(httpUrlBuilder.build());
} else {
//如果原请求是表单请求
if (oldRequest.body() instanceof FormBody) {
FormBody.Builder formBodyBuilder = new FormBody.Builder();
for (String key : params.keySet()) {
formBodyBuilder.add(key, params.get(key));
}
FormBody oldFormBody = (FormBody) oldRequest.body();
int size = oldFormBody.size();
for (int i = 0; i < size; i++) {
formBodyBuilder.add(oldFormBody.name(i), oldFormBody.value(i));
}
newRequestBuilder.post(formBodyBuilder.build());
}
// TODO: 处理其它类型的request.body
}
return chain.proceed(newRequestBuilder.build());
}
return chain.proceed(oldRequest);
}
}
定义Subscriber
public abstract class BaseSubscriber<T> extends DisposableSubscriber<Result<T>> {
@Override public void onNext(Result<T> result) {
//业务代码为成功则将具体的数据返回,否则利用EventBus将错误发出去
if (result.getCode() == Constants.NET_CODE_SUCCESS) {
handlerSuccess(result.getData());
} else {
EventBus.getDefault().post(new MsgEvent(result.getCode(), result.getMsg()));
}
}
@Override public void onError(Throwable t) {
MsgEvent msgEvent;
//处理常见的几种连接错误
if (t instanceof SocketTimeoutException) {
msgEvent = new MsgEvent(Constants.NET_CODE_SOCKET_TIMEOUT, Constants.SOCKET_TIMEOUT_EXCEPTION);
} else if (t instanceof ConnectException) {
msgEvent = new MsgEvent(Constants.NET_CODE_CONNECT, Constants.CONNECT_EXCEPTION);
} else if (t instanceof UnknownHostException) {
msgEvent = new MsgEvent(Constants.NET_CODE_UNKNOWN_HOST, Constants.UNKNOWN_HOST_EXCEPTION);
} else {
msgEvent = new MsgEvent(Constants.NET_CODE_ERROR, t.getMessage());
}
EventBus.getDefault().post(msgEvent);
}
@Override public void onComplete() {
}
//请求成功返回结果
public abstract void handlerSuccess(T t);
}
带有进度条的Subscriber
public abstract class ProgressSubscriber<T> extends BaseSubscriber<T> {
private ProgressDialog dialog;
protected ProgressSubscriber(ProgressDialog dialog) {
this.dialog = dialog;
}
@Override public void onError(Throwable e) {
super.onError(e);
if (dialog != null) dialog.dismiss();
}
@Override public void onComplete() {
super.onComplete();
if (dialog != null) dialog.dismiss();
}
}
为了对请求进行预处理和简化每次都要写的线程步骤,定义了如下的一个类
public class RxSchedulers {
/**
* 基本请求
*/
public static <T> FlowableTransformer<T, T> io_main(final Context context) {
return new FlowableTransformer<T, T>() {
@Override public Publisher<T> apply(@NonNull Flowable<T> upstream) {
return upstream
.subscribeOn(Schedulers.io())
.doOnSubscribe(new Consumer<Subscription>() {
@Override
public void accept(@NonNull Subscription subscription) throws Exception {
//如果无网络连接,则直接取消了
if (!NetUtil.isConnected(context)) {
subscription.cancel();
MsgEvent msgEvent = new MsgEvent(Constants.NET_CODE_CONNECT, Constants.CONNECT_EXCEPTION);
EventBus.getDefault().post(msgEvent);
}
}
})
.observeOn(AndroidSchedulers.mainThread());
}
};
}
/**
* 带进度条的请求
*/
public static <T> FlowableTransformer<T, T> io_main(final Context context, final ProgressDialog dialog) {
return new FlowableTransformer<T, T>() {
@Override public Publisher<T> apply(@NonNull Flowable<T> upstream) {
return upstream
//为了让进度条保持一会儿做了个延时
.delay(1, TimeUnit.SECONDS)
.subscribeOn(Schedulers.io())
.doOnSubscribe(new Consumer<Subscription>() {
@Override
public void accept(@NonNull final Subscription subscription) throws Exception {
if (!NetUtil.isConnected(context)) {
subscription.cancel();
MsgEvent msgEvent = new MsgEvent(Constants.NET_CODE_CONNECT, Constants.CONNECT_EXCEPTION);
EventBus.getDefault().post(msgEvent);
} else {
//启动进度显示,取消进度时会取消请求
if (dialog != null) {
dialog.setCanceledOnTouchOutside(false);
dialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override public void onCancel(DialogInterface dialog) {
subscription.cancel();
}
});
dialog.show();
}
}
}
})
.observeOn(AndroidSchedulers.mainThread());
}
};
}
}
定义retrofit的单例,结合Android的生命周期来管理订阅
public class RetrofitManager {
private static ArrayMap<String, CompositeDisposable> netManager = new ArrayMap<>();
public static Retrofit getInstance() {
return Instance.retrofit;
}
private static class Instance {
private static String baseUrl = BaseApp.getAppContext().getBaseUrl();
private static Retrofit retrofit = getRetrofit();
private static Retrofit getRetrofit() {
OkHttpClient.Builder okHttpBuilder = new OkHttpClient.Builder();
//debug模式添加log信息拦截
if (BaseApp.getAppContext().isDebug()) {
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
okHttpBuilder.addInterceptor(interceptor);
}
okHttpBuilder.addInterceptor(new HeaderInterceptor());
okHttpBuilder.addInterceptor(new ParamsInterceptor());
//设置网络连接失败时自动重试
okHttpBuilder.retryOnConnectionFailure(true);
//设置连接超时
okHttpBuilder.connectTimeout(5, TimeUnit.SECONDS);
//设置写超时
okHttpBuilder.writeTimeout(10, TimeUnit.SECONDS);
//设置读超时
okHttpBuilder.readTimeout(10, TimeUnit.SECONDS);
Retrofit.Builder retrofitBuilder = new Retrofit.Builder();
retrofitBuilder.baseUrl(baseUrl);
retrofitBuilder.client(okHttpBuilder.build());
retrofitBuilder.addCallAdapterFactory(RxJava2CallAdapterFactory.create());
retrofitBuilder.addConverterFactory(GsonConverterFactory.create());
return retrofitBuilder.build();
}
}
//为了避免错误的取消了,key建议使用packagename + calssName
public static void add(String key, Disposable disposable) {
if (netManager.containsKey(key)) {
netManager.get(key).add(disposable);
} else {
CompositeDisposable compositeDisposable = new CompositeDisposable();
compositeDisposable.add(disposable);
netManager.put(key, compositeDisposable);
}
}
public static void remove(String key) {
if (netManager.containsKey(key)) {
CompositeDisposable compositeDisposable = netManager.get(key);
compositeDisposable.clear();
}
}
}
BaseActivity中的配置
@Override protected void onResume() {
super.onResume();
EventBus.getDefault().register(this);
}
@Override protected void onPause() {
super.onPause();
EventBus.getDefault().unregister(this);
}
@Override protected void onDestroy() {
super.onDestroy();
String key = mContext.getPackageName() + "." + mContext.getClass().getSimpleName();
RetrofitManager.remove(key);
}
protected void addDisposable(Disposable disposable) {
String key = mContext.getPackageName() + "." + mContext.getClass().getSimpleName();
RetrofitManager.add(key, disposable);
}
简单使用
- 定义接口
@GET("api/common/getQiNiuToken")
Flowable<Result<String>> getQiNiuToken();
- 网络请求调起
//不带进度的网络请求
addDisposable(RetrofitManager.getInstance()
.create(ICommon.class)
.getQiNiuToken()
.compose(RxSchedulers.<Result<String>>io_main(mContext))
.subscribeWith(new BaseSubscriber<String>() {
@Override public void handlerSuccess(String s) {
}
})
);
//带进度的网络请求
ProgressDialog dialog = new ProgressDialog(mContext, ProgressDialog.THEME_HOLO_DARK);
dialog.setMessage("请稍后。。。");
addDisposable(RetrofitManager.getInstance()
.create(ICommon.class)
.getQiNiuToken()
.compose(RxSchedulers.<Result<String>>io_main(mContext, dialog))
.subscribeWith(new ProgressSubscriber<String>(dialog) {
@Override public void handlerSuccess(String s) {
}
})
);
以上就是我的网络请求封装全部代码。
网友评论
private int code;
private String msg;
private T result;
}
@get("api/v1/common/index")
Flowable<BaseEntity<City>> region();
BaseRetrofit
.getInstance()
.create(BaseRetrofitApi.class)
.region()
.compose(BaseRxSchedulers.<BaseEntity<City>>io_main(this))
.subscribeWith(new BaseSubscriber<City>() {
@Override
public void onSuccess(City city) {
LogUtils.e(city.getData().get(0).getBIANMA());
}
});
@Override
public void onNext(BaseEntity<T> baseEntity) {
if (baseEntity.getCode() == Constants.NET_CODE_SUCCESS) {
onSuccess(baseEntity.getResult());
} else {
ToastUtils.showToast(baseEntity.getMsg());
}
}
我的配置是这样的
compile 'com.squareup.retrofit2:retrofit:2.2.0'
compile 'com.squareup.retrofit2:converter-gson:2.2.0'
compile 'com.squareup.retrofit2:adapter-rxjava2:2.2.0'
compile 'com.squareup.okhttp3:logging-interceptor:3.6.0'
compile 'io.reactivex.rxjava2:rxjava:2.0.8'
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'