RxJava2+Retrofit2实现网络请求封装

网络请求一般会封装在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 getRequestHeader();

/**
 * 配置公共请求参数
 */
public abstract ArrayMap 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 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 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 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 extends DisposableSubscriber> {

    @Override public void onNext(Result 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 extends BaseSubscriber {
    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  FlowableTransformer io_main(final Context context) {
        return new FlowableTransformer() {
            @Override public Publisher apply(@NonNull Flowable upstream) {
                return upstream
                        .subscribeOn(Schedulers.io())
                        .doOnSubscribe(new Consumer() {
                            @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  FlowableTransformer io_main(final Context context, final ProgressDialog dialog) {
        return new FlowableTransformer() {
            @Override public Publisher apply(@NonNull Flowable upstream) {
                return upstream
                        //为了让进度条保持一会儿做了个延时
                        .delay(1, TimeUnit.SECONDS) 
                        .subscribeOn(Schedulers.io())
                        .doOnSubscribe(new Consumer() {
                            @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 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);
    }

简单使用

  1. 定义接口
 @GET("api/common/getQiNiuToken")
Flowable> getQiNiuToken();
  1. 网络请求调起
//不带进度的网络请求
addDisposable(RetrofitManager.getInstance()
                .create(ICommon.class)
                .getQiNiuToken()
                .compose(RxSchedulers.>io_main(mContext))
                .subscribeWith(new BaseSubscriber() {
                    @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.>io_main(mContext, dialog))
                .subscribeWith(new ProgressSubscriber(dialog) {
                    @Override public void handlerSuccess(String s) {

                    }
                })
        );

以上就是我的网络请求封装全部代码。

你可能感兴趣的:(RxJava2+Retrofit2实现网络请求封装)