Retrofit2的封装优化

这是一个基于Retrofit2+RxJava2封装优化

对RxJava与Retrofit不了解的朋友需要优先进主页或者本人写的系统导读

主页

Rxjava
RxAndroid
Retrofit

系列导读

RxJava2.x的集成及用法详解
Retrofit2使用教程
RxJava2+Retrofit2结合使用

用途
  • 避免重复创建Retrofit实列.
  • 调用方便简洁.
  • 无需重复设置属性的步骤.
  • 支持扩展APIService
  • 统一处理无网络情况,和支持加载进度
  • 结合RxJava
  • 支持异步请求统一回调
  • 链式调用

其实啊这些功能实现起来都不难,最重要的还是思想,看你想怎么玩,好啦,学习之前先来看看优化前后的区别,学习起来更有劲儿了是吧

优化前调用

        //创建日志拦截器
        HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
        httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);//设定日志级别
        //创建OkHttpClient
        OkHttpClient mOkHttpClient = new OkHttpClient.Builder()
                .connectTimeout(ApiService.HTTP_TIME, TimeUnit.SECONDS)
                .readTimeout(ApiService.HTTP_TIME, TimeUnit.SECONDS)
                .writeTimeout(ApiService.HTTP_TIME, TimeUnit.SECONDS)
                .addInterceptor(httpLoggingInterceptor)//添加拦截器
                .build();

        //创建Retrofit
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(ApiService.BASE_URL)
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .client(mOkHttpClient)
                .build();

        //创建接口实现类
        ApiService apiService = retrofit.create(ApiService.class);

        Observable<CallHomeBean> callHome = apiService.getCallHome(getString(R.string.phone_num), getString(R.string.phone_key));

        callHome
                .subscribeOn(Schedulers.io())
                .map(new Function<CallHomeBean, String>() {
                    @Override
                    public String apply(CallHomeBean callHomeBean) throws Exception {
                        return callHomeBean.getResult().getProvince() + callHomeBean.getResult().getCity();
                    }
                })
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Consumer<String>() {
                    @Override
                    public void accept(String s) throws Exception {
                        tvPhone.setText(s);
                    }
                });

优化后调用

        RetrofitFactory
                        .getInstence()
                        .getPhoneInfo(getString(R.string.phone_location), getString(R.string.phone_key),new BaseObserver<PhoneInfo>() {
                            @Override
                            protected void onSuccees(BaseEntity<PhoneInfo> t){
                                tvPhone.setText(t.getResult().getProvince());
                            }

                            @Override
                            protected void onFailure(Throwable e, boolean isNetWorkError){
                                tvPhone.setText(e.getMessage());
                            }
                        });

这里可以看到只是实例化了一个单例的RetrofitFactory,调用了一个方法。想必大家已经知道代码去哪了

1.RetrofitFactory

        public class RetrofitFactory {

            private final ApiService mApiService;

            private static RetrofitFactory mRetrofitFactory;

            private RetrofitFactory() {
                //创建日志拦截器
                HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
                httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);//设定日志级别
                //创建OkHttpClient
                OkHttpClient mOkHttpClient = new OkHttpClient.Builder()
                        .connectTimeout(ApiService.HTTP_TIME, TimeUnit.SECONDS)
                        .readTimeout(ApiService.HTTP_TIME, TimeUnit.SECONDS)
                        .writeTimeout(ApiService.HTTP_TIME, TimeUnit.SECONDS)
                        .addInterceptor(httpLoggingInterceptor)//添加拦截器
                        .build();

                //创建Retrofit
                Retrofit retrofit = new Retrofit.Builder()
                        .baseUrl(ApiService.BASE_URL)
                        .addConverterFactory(GsonConverterFactory.create())//添加gson转换器
                        .addCallAdapterFactory(RxJava2CallAdapterFactory.create())//添加rxjava2转换器
                        .client(mOkHttpClient)
                        .build();

                //创建接口实现类
                mApiService = retrofit.create(ApiService.class);

            }
            // 懒汉式单例模式
            public static RetrofitFactory getInstence() {
                if (mRetrofitFactory == null) {
                    // 静态方法,使用当前类本身充当进程锁
                    synchronized (RetrofitFactory.class) {
                        if (mRetrofitFactory == null)
                            mRetrofitFactory = new RetrofitFactory();
                    }
                }
                return mRetrofitFactory;
            }
            //请求网络的API接口类
            public ApiService API() {
                return mApiService;
            }
            //构建API接口实现方法
            public void getPhoneInfo(String phone, String key, BaseObserver<PhoneInfo> scheduler) {
                API()
                        .getPhoneMsg(phone, key)
                        .subscribeOn(Schedulers.io())
                        .unsubscribeOn(Schedulers.io())
                        .observeOn(AndroidSchedulers.mainThread())
                        .subscribe(scheduler);
            }
            //构建API接口实现方法
            public void getWeatherInfo(Map<String ,String> map, BaseObserver<WeatherInfo> scheduler) {
                API()
                        .getWeather(map)
                        .subscribeOn(Schedulers.io())
                        .unsubscribeOn(Schedulers.io())
                        .observeOn(AndroidSchedulers.mainThread())
                        .subscribe(scheduler);
            }
        }

RetrofitFactory主要负责创建具体Retrofit、调度分发请求、设置格式工厂、构建OkHttpClient、构建日志拦截器、构建Retrofit的接口service。
那么有的朋友可能发现了在指定生产线程和消费线程的时候,步骤有点麻烦,每个api都得进行指定线程,那么可以利用rxJava的转换器写一个Transformer


        public ObservableTransformer threadTransformer() {
            return new ObservableTransformer() {
                @Override
                public ObservableSource apply(Observable observable) {
                    return observable
                            .subscribeOn(Schedulers.io())
                            .unsubscribeOn(Schedulers.io())
                            .observeOn(AndroidSchedulers.mainThread());
                }
            };
        }

那么再次调用的时候就变成了这样

    public void getPhoneInfo(String phone, String key, BaseObserver<PhoneInfo> scheduler) {
        API()
                .getPhoneMsg(phone, key)
                .compose(threadTransformer())
                .subscribe(scheduler);
    }

    public void getWeatherInfo(Map<String ,String> map, BaseObserver<WeatherInfo> scheduler) {
        API()
                .getWeather(map)
                .compose(threadTransformer())
                .subscribe(scheduler);
    }

这里可以看到最后一个形参并不是普通的Observer,而是一个经过二次封装的对象,接着往下看

3. BaseObserver

    public abstract class BaseObserver<T> implements Observer<BaseEntity<T>> {

        private static final String TAG = BaseObserver.class.getSimpleName();
        private Context mContext;

        protected BaseObserver(){ }

        protected BaseObserver(Context context) { this.mContext = context; }

        @Override
        public void onNext(BaseEntity<T> tBaseEntity) {
            if (tBaseEntity.isSuccess()) {
                try {
                    onSuccees(tBaseEntity);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            } else {
                try {
                    onCodeError(tBaseEntity.getError_code());
                    onError(new Throwable(tBaseEntity.getReason()));
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }

        @Override
        public void onError(Throwable e) {
            try {
                if (e instanceof ConnectException
                        || e instanceof TimeoutException
                        || e instanceof NetworkErrorException
                        || e instanceof UnknownHostException) {
                    onFailure(e, true);
                } else {
                    onFailure(e, false);
                }
            } catch (Exception e1) {
                e1.printStackTrace();
            }
        }

        @Override
        public void onComplete() { }

        @Override
        public void onSubscribe(Disposable d) { }

        /**
         * 返回成功
         *
         * @param data
         * @throws Exception
         */
        protected abstract void onSuccees(BaseEntity<T> data) throws Exception;

        /**
         * 返回失败
         *
         * @param e
         * @param isNetWorkError 是否是网络错误
         * @throws Exception
         */
        protected abstract void onFailure(Throwable e, boolean isNetWorkError) throws Exception;

        /**
         * 返回成功了,但是code错误
         *
         * @param error
         * @throws Exception
         */
        protected void onCodeError(int error) throws Exception { }

可以看出BaseObserver只做了三件事:采用适配器模式对Observer抽象方法重新封装、统一处理网络的异常、通过泛型限定了实例类的类型BaseEntity<\T>。最后再看看BaseEntity干了些啥

4. BaseEntity

public class BaseEntity<T> {
    private static int SUCCESS_CODE = 0;//成功的code
    private String reason;//请求成功或失败描述
    private int error_code;//错误码
    private T result;//数据集

    public boolean isSuccess() {
        return getError_code() == SUCCESS_CODE;
    }

    public String getReason() {
        return reason;
    }

    public void setReason(String reason) {
        this.reason = reason;
    }

    public T getResult() {
        return result;
    }

    public void setResult(T result) {
        this.result = result;
    }

    public int getError_code() {
        return error_code;
    }

    public void setError_code(int error_code) {
        this.error_code = error_code;
    }
}

通常服务器端会返回统一的数据格式,只是数据略有区分,BaseEntity的作用就是抽取数据中的公共属性,例如:

/**
 * @description 此json只有中间result的内容不同其他都相同,所以可抽取的属性包括:
 *          resultcode、reason、error_code和外层的result
 */
1. {                                                     2. {
        "resultcode":"200",                                     "resultcode":"200",
        "reason":"Return Successd!",                            "reason":"Return Successd!",
        "result":{                                              "result":{
        "province":"浙江",                                      "temp": "21", /*当前温度*/
        "city":"杭州",                                          "wind_direction": "西风",   /*当前风向*/
        "areacode":"0571",                                      "wind_strength": "2级",  /*当前风力*/
        "zip":"310000",                                         "humidity": "4%",   /*当前湿度*/
        "company":"中国移动",                                    "time": "14:25"    /*更新时间*/
        "card":""
        }  
        "error_code": 0                                             }
                                                                "error_code": 0
        }                                                           }

5. ApiService


    /**
     * 测试接口使用的是聚合数据提供的免费API
     * 地址:https://www.juhe.cn/
     */
    public interface ApiService {
    //    用Retrofit需要后台接口遵循REST风格的请求
    //    请求示例:http://apis.juhe.cn/mobile/get?phone=1351103&key=您申请的KEY
    //    基本地址:http://apis.juhe.cn
    //    功能地址:/mobile/get
    //    请求参数:?phone=1351103&key=790c971125********190725627e5ca5

        String BASE_URL = "http://apis.juhe.cn/";

        //网络请求时长
        int HTTP_TIME = 5000;

        /**
         * 接口1:获取来电归属地, API一定是以 "/" 开头,这是Retrofit规范
         */
        @GET("mobile/get")
        Observable<BaseEntity<PhoneInfo>> getPhoneMsg(@Query("phone") String phone, @Query("key") String key);

        /**
         * 接口2:获取天气信息
         */
        @GET("/weather/index")
        Observable<BaseEntity<WeatherInfo>> getWeather(@QueryMap Map<String, String> options);
    }

请求网络的API接口类,这里你可以增加你需要的请求接口,例如json数据的请求啊、单个或多个图片、文件的上传下载等等。

Demo下载传送门

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值