美文网首页安卓开发博客Android
Retrofit + RxJava + OkHttp封装网络请求

Retrofit + RxJava + OkHttp封装网络请求

作者: 牧头码尾 | 来源:发表于2018-02-09 15:07 被阅读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的形式返回。

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

    相关文章

      网友评论

        本文标题:Retrofit + RxJava + OkHttp封装网络请求

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