安卓开发博客Android

Retrofit + RxJava + OkHttp封装网络请求

2018-02-09  本文已影响197人  牧头码尾

前言:

网络请求可以算是一个应用最基本的功能模块之一了,那么如何让网络请求变的更加方便实用呢?今天我就给大家介绍一下目前最主流的网络请求框架,Retrofit + RxJava + OkHttp,那么接下来,我们先简单介绍一下这三个模块,最后再结合在一起做一个简单的分装。

Retrofit

Retrofit是Square公司开发的一款针对Android网络请求的框架,Retrofit2底层基于OkHttp实现的,OkHttp现在已经得到Google官方认可,目前大部分
app都采用OkHttp做网络请求,其源码详见OkHttp Github

Retrofit的简单使用

具体参照以下博文
[Android] Retrofit 初步使用

RxJava

RxJava 在 GitHub 主页上的自我介绍是 "a library for composing asynchronous and event-based programs using observable sequences for the Java VM"(一个在 Java VM 上使用可观测的序列来组成异步的、基于事件的程序的库)。这就是 RxJava ,概括得非常精准。

好吧,再偷个懒,关于RxJava请参考以下几篇博文:
给 Android 开发者的 RxJava 详解
这可能是最好的RxJava 2.x 教程(完结版)

OkHttp

OkHttp目前已经得到Google的官方认可,也是目前主流的网络请求框架,具体用法,大家参照官网http://square.github.io/okhttp/,毕竟接下来把它和Retrofit和RxJava结合的分装才是重点。

Retrofit + RxJava + OkHttp封装(闪亮登场)

一:创建Retrofit的管理类RetrofitHelper

/**
 * 网络请求Retrofit的帮助类
 * Created by Administrator on 2017/11/2.
 */

public class RetrofitHelper {

    private static final int DEFAULT_TIME_OUT = 30;//超时时间 10s
    private static final int DEFAULT_READ_TIME_OUT = 30;
    private Retrofit mRetrofit;

    private RetrofitHelper(){
        final OkHttpClient.Builder builder = new OkHttpClient.Builder();
        builder.connectTimeout(DEFAULT_TIME_OUT, TimeUnit.SECONDS);//连接超时时间
        builder.readTimeout(DEFAULT_READ_TIME_OUT, TimeUnit.SECONDS);//读操作超时时间

        // 添加公共参数拦截器
        HttpCommonInterceptor commonInterceptor = new HttpCommonInterceptor.Builder()
                .addHeaderParams("cookie", OrtherUtil.getCookie(BasicUtil.getUserId()))//添加的公共请求头部(即cookie信息)
                .build();
        builder.addInterceptor(commonInterceptor);
        mRetrofit = new Retrofit.Builder()
                .client(builder.build())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .addConverterFactory(MyGsonConverterFactory.create())
                .baseUrl(Interface_Url.HTTPURL)//添加请求的URL地址(前面公共部分)
                .build();
    }

    //使用静态内部类的方式获取单例模式
//    private static class SingletonHolder{
//        private static final RetrofitHelper INSTANCE = new RetrofitHelper();
//    }
    //获取RetrofitHelper对象,为保证每次的cookie信息为最新的,所以每次调用都重新给mRetrofit赋值
    public static RetrofitHelper getInstance(){
//        return SingletonHolder.INSTANCE;
        return new RetrofitHelper();
    }
    /**
     * 获取服务对象 以接口的形式
     * @param classz 接口类
     * @param <T>
     * @return
     */
    public <T> T getService(Class<T> classz){
        return mRetrofit.create(classz);
    }
}

其中为了保证每次获取的网络请求中cookie信息都是最新的(cookie中包含时间戳信息),所以每次请求时都是重新构建了retrofit的请求参数,如果项目中的cookie信息固定,则可用上面注释掉的单例模式获取RetrofitHelper
为了方便对请求的结果做统一管理,在构建请求时添加了自定义的
MyGsonConverterFactory类,该类继承Converter.Factory,实现如下:

/**
 * 自定义GsonConverterFactory
 */

public final class MyGsonConverterFactory extends Converter.Factory{

        /**
         * Create an instance using a default {@link Gson} instance for conversion. Encoding to JSON and
         * decoding from JSON (when no charset is specified by a header) will use UTF-8.
         */
        public static MyGsonConverterFactory create() {
            return create(new Gson());
        }

        /**
         * Create an instance using {@code gson} for conversion. Encoding to JSON and
         * decoding from JSON (when no charset is specified by a header) will use UTF-8.
         */
        @SuppressWarnings("ConstantConditions") // Guarding public API nullability.
        public static MyGsonConverterFactory create(Gson gson) {
            if (gson == null) throw new NullPointerException("gson == null");
            return new MyGsonConverterFactory(gson);
        }

        private final Gson gson;

        private MyGsonConverterFactory(Gson gson) {
            this.gson = gson;
        }

        @Override
        public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
                                                                Retrofit retrofit) {
//            TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
            return new MyGsonResponseBodyConverter<>(gson, type);
        }

        @Override
        public Converter<?, RequestBody> requestBodyConverter(Type type,
                                                              Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
            TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
            return new MyGsonRequestBodyConverter<>(gson, adapter);
        }
}

其中主要修改了responseBodyConverterrequestBodyConverter方法。这两个方法主要是对返回的结果以及请求的参数进行处理,具体实现如下:

/**
 * 重写GsonResponseBodyConverter方便获取网络返回的原始数据
 * Created by Administrator on 2017/11/3.
 */

final class MyGsonResponseBodyConverter<T> implements Converter<ResponseBody, T>{

    private final Gson gson;
    private final Type type;

    MyGsonResponseBodyConverter(Gson gson, Type type) {
        this.gson = gson;
        this.type = type;

    }
    @Override
    public T convert(ResponseBody value) throws IOException{
        JSONObject jsonObject;
        String response = value.string();
        //Log.e("jk",response);
       // BaseResponseBean baseResponse = gson.fromJson(response,type);
        try {
            jsonObject = new JSONObject(response);
            return (T) jsonObject;
        } catch (JSONException e) {
            e.printStackTrace();
            return null;
        }
    }
}
final class MyGsonRequestBodyConverter<T> implements Converter<T, RequestBody>{
    private static final MediaType MEDIA_TYPE = MediaType.parse("application/json; charset=UTF-8");
    private static final Charset UTF_8 = Charset.forName("UTF-8");

    private final Gson gson;
    private final TypeAdapter<T> adapter;

    MyGsonRequestBodyConverter(Gson gson, TypeAdapter<T> adapter) {
        this.gson = gson;
        this.adapter = adapter;
    }

    @Override public RequestBody convert(T value) throws IOException{
        Buffer buffer = new Buffer();
        Writer writer = new OutputStreamWriter(buffer.outputStream(), UTF_8);
        JsonWriter jsonWriter = gson.newJsonWriter(writer);
        LogController.i("jk",jsonWriter.toString());
        adapter.write(jsonWriter, value);
        jsonWriter.close();
        return RequestBody.create(MEDIA_TYPE, buffer.readByteString());
    }
}

二:定义网络请求返回的实体类(基类)

/**
 * 网络请求结果的基类
 * Created by Administrator on 2017/11/3.
 */

public class BaseResponseBean<T>{
    public int errcode;//错误码
    public String errmsg;//错误信息 当errcode不为0时返回
    public T replydata;//返回的关键数据,每个接口的对象都不一样
    public boolean isSuccess(){
        return errcode == 0;//为0时请求成功
    }
}

这个返回的基类根据服务器返回的参数类型来定,分为固定参数errcode(错误码)和errmsg(错误信息),以及可变参数replydata(真正返回的数据类),这里返回类型用泛型T表示

三:结合Rxjava定义网络请求工具类

/**
 * 网络请求工具类
 * Created by Administrator on 2017/11/2.
 */

public class HttpUtils {

    /**
     * 结合Rxjava进行网络请求
     * @param observable
     * @param resultListener
     * @param <T>
     */
    public static<T> void requestNet(final Observable observable, final OnResultListener resultListener){

        if(!NetUtil.isNetworkAvailabe(BaseApplication.getAppContext())){//网络不可用
            resultListener.onError(new Exception("网络错误"),"网络未连接",-3);
            return;
        }
        setSubscriber(observable, new Observer<JSONObject>(){
            @Override
            public void onSubscribe(Disposable d) {

            }

            @Override
            public void onNext(JSONObject jsonObject) {
                if(resultListener != null){
                    LogController.e("jk","请求结果:"+jsonObject.toString());
                    BaseResponseBean baseResponse = new Gson().fromJson(jsonObject.toString(),BaseResponseBean.class);
                    if(baseResponse.isSuccess()){//数据返回成功

                        resultListener.onSuccess(jsonObject);//返回整个json数据
                    }else{//返回错误码,并进行统一的错误处理
                        switch(baseResponse.errcode){
                            case -1:
                                resultListener.onError(new Exception("服务器错误"),baseResponse.errmsg,baseResponse.errcode);
                                break;
                            case 1001:
                                resultListener.onError(new Exception("请求错误"),baseResponse.errmsg,baseResponse.errcode);
                                break;
                            case 1002:
                                resultListener.onError(new Exception("请求错误"),baseResponse.errmsg,baseResponse.errcode);
                                break;
                            case 1003:
                                resultListener.onError(new Exception("请求错误"),baseResponse.errmsg,baseResponse.errcode);
                                break;
                            case 1004:
                                resultListener.onError(new Exception("请求错误"),baseResponse.errmsg,baseResponse.errcode);
                                break;
                            case 1005:
                                resultListener.onError(new Exception("请求错误"),baseResponse.errmsg,baseResponse.errcode);
                                break;
                            default:
                                resultListener.onError(new Exception("其他错误"),baseResponse.errmsg,baseResponse.errcode);
                                break;
                        }
                    }
                }
            }

            @Override
            public void onError(Throwable e) {
                if(e != null && resultListener != null){
                    resultListener.onError(e,e.getMessage(),-2);
                }else if(resultListener != null){
                    resultListener.onError(new Exception("网络错误"),"网络请求失败",-2);
                    return;
                }
            }

            @Override
            public void onComplete() {

            }
        });


    }

    public static<T> void setSubscriber(Observable<T> observable, Observer<T> observer){
        observable.subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(observer);
    }


    /**
     * 获取RequestBody,用于请求接口时,方便传递参数
     * @param jsonObject
     * @return
     */
    public static RequestBody getRequestBody(JSONObject jsonObject){
        //添加传递的参数,以json数据的格式
        RequestBody body = RequestBody.create(MediaType.parse("application/json"),jsonObject.toString());
        return body;
    }

    //网络请求接口的回调
    public interface OnResultListener<T>{
        void onSuccess(T t);
        void onError(Throwable error, String msg, int err_code);
    }
}

四:定义请求接口和方法,进行网络请求

这里以获取应用最新版本的请求接口做个示范(get请求)

public interface IVersionInter {

    @GET(InterConstant.GETVERSONURL)
    Observable<BaseResponseBean> getVersion();
}
        //获取接口对象
        IVersionInter service = RetrofitHelper.getInstance().getService(IVersionInter.class);
        //调用接口方法,得到返回的observable
        Observable<BaseResponseBean> observable = service.getVersion();
        HttpUtils.requestNet(observable, new HttpUtils.OnResultListener() {
            @Override
            public void onSuccess(Object o) {
               Gson gson = new Gson();
               //获取到的版本实体类
               VersionRespond respond = gson.fromJson(o.toString(), VersionRespond .class);
            }

            @Override
            public void onError(Throwable error, String msg, int err_code) {
                //打印错误
                LogController.e(TAG,msg);
            }
        });

同样的,如果是post请求,只需在接口的方法中添加请求参数即可,改写如下:

public interface IVersionInter {

    @POST(InterConstant.GETVERSONURL)
    Observable<BaseResponseBean> getVersion(@Body RequestBody body);
}
        //添加传递的参数,以json数据的格式
        RequestBody body = RequestBody.create(MediaType.parse("application/json"), getJsonObject().toString());
        //获取接口对象
        IVersionInter service = RetrofitHelper.getInstance().getService(IVersionInter.class);
        //调用接口方法,得到返回的observable
        Observable<BaseResponseBean> observable = service.getVersion(body );
        HttpUtils.requestNet(observable, new HttpUtils.OnResultListener() {
            @Override
            public void onSuccess(Object o) {
               Gson gson = new Gson();
               //获取到的版本实体类
               VersionRespond respond = gson.fromJson(o.toString(), VersionRespond .class);
            }

            @Override
            public void onError(Throwable error, String msg, int err_code) {
                //打印错误
                LogController.e(TAG,msg);
            }
        });

其中getJsonObject()则返回需要传递的请求参数,并分装成JSONObject的形式返回。

最后,获取到数据,以及返回的错误码该如何处理,具体的业务处理就按照实际需求来了,我这里只是做了一个简单的处理。
上一篇下一篇

猜你喜欢

热点阅读