RxJava2 Retrofit2 网络框架简洁轻便封装

作者: JohnsonZZZ | 来源:发表于2017-12-07 13:12 被阅读406次

    前言

    RxJava2、Retrofit2火了有一段时间了,前段时间给公司的项目引入了这方面相关的技术,在此记录一下相关封装的思路。

    需求

    封装之前要先明白需要满足哪些项目需求。

    • RxJava2衔接Retrofit2
    • Retrofit2网络框架异常的统一处理
    • 兼容fastjson(可选)
    • RxJava2内存泄漏的处理
    • 异步请求加入Loading Dialog

    1.依赖

        implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'
        implementation 'io.reactivex.rxjava2:rxjava:2.1.3'
        implementation 'com.squareup.retrofit2:retrofit:2.3.0'
        implementation 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'
        implementation 'com.squareup.okhttp3:okhttp:3.9.0'
        implementation 'com.trello.rxlifecycle2:rxlifecycle-components:2.2.0'
        implementation 'com.alibaba:fastjson:1.1.59.android'//可选其它框架比如Gson
    

    2.RxJava2衔接Retrofit2

    先封装一个网络框架的管理类,方便调用

    public class RxHttp {
        private final String BASE_URL = "https://github.com/";
        private Map<String, Retrofit> mRetrofitMap = new HashMap<>();
    
        private RxHttp() {
    
        }
    
        /**
         * 单例模式
         * @return
         */
        public static RxHttp getInstance() {
            return RxHttpHolder.sInstance;
        }
    
        private static class RxHttpHolder{
            private final static RxHttp sInstance = new RxHttp();
        }
    
        public Retrofit getRetrofit(String serverUrl) {
            Retrofit retrofit;
            if (mRetrofitMap.containsKey(serverUrl)) {
                retrofit = mRetrofitMap.get(serverUrl);
            } else {
                retrofit = createRetrofit(serverUrl);
                mRetrofitMap.put(serverUrl, retrofit);
            }
            return retrofit;
        }
    
        public SyncServerService getSyncServer(){
            return getRetrofit(BASE_URL).create(SyncServerService.class);
        }
    
    
        /**
         *
         * @param baseUrl  baseUrl要以/作为结尾  eg:https://github.com/
         * @return
         */
        private Retrofit createRetrofit(String baseUrl) {
            OkHttpClient client = new OkHttpClient().newBuilder()
                    .readTimeout(30, TimeUnit.SECONDS)
                    .connectTimeout(30, TimeUnit.SECONDS)
                    .retryOnConnectionFailure(true)
                    .build();
    
            return new Retrofit.Builder()
                    .baseUrl(baseUrl)
                    .addConverterFactory(FastJsonConverterFactory.create())
                    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                    .client(client)
                    .build();
        }
    
    }
    

    3.Restful风格接口

    public interface SyncServerService {
    
        @GET("service/mobile/IsLatestVersion.ashx")
        Observable<Response<String>> getLatestVersion(@Query("SoftwareID") String SoftwareID,
                                                      @Query("ClientVersion") String ClientVersion);
    }
    

    服务端返回的基本类型,在导入类的时候特别需要注意区分该Response类型

    public class Response<T> {
    
        public int ret;//约定  -1为server返回数据异常  200为正常范围
        public String msg;
        public T data;
    
        public int getRet() {
            return ret;
        }
    
        public void setRet(int ret) {
            this.ret = ret;
        }
    
        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;
        }
    }
    

    4.fastjson的支持

    由于项目中采用了fastjson,square的开源项目尚未实现对fastjson的支持,但是保留了代码的扩展,这边可以自己封装一下fastjson的转换器。

    public class FastJsonConverterFactory extends Converter.Factory {
    
        private final SerializeConfig mSerializeConfig;
    
        private FastJsonConverterFactory(SerializeConfig serializeConfig) {
            this.mSerializeConfig = serializeConfig;
        }
    
        public static FastJsonConverterFactory create() {
            return create(SerializeConfig.getGlobalInstance());
        }
    
        public static FastJsonConverterFactory create(SerializeConfig serializeConfig) {
            return new FastJsonConverterFactory(serializeConfig);
        }
    
        @Override
        public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
            return new FastJsonRequestBodyConverter<>(mSerializeConfig);
        }
    
        @Override
        public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
            return new FastJsonResponseBodyConvert<>(type);
        }
    }
    
    final class FastJsonRequestBodyConverter<T> implements Converter<T, RequestBody> {
    
        private final MediaType MEDIA_TYPE = MediaType.parse("application/json; charset=UTF-8");
    
        private SerializeConfig mSerializeConfig;
    
        public FastJsonRequestBodyConverter(SerializeConfig serializeConfig) {
            this.mSerializeConfig = serializeConfig;
        }
    
        @Override
        public RequestBody convert(T value) throws IOException {
            return RequestBody.create(MEDIA_TYPE, JSON.toJSONBytes(value, mSerializeConfig));
        }
    }
    
    final class FastJsonResponseBodyConvert<T> implements Converter<ResponseBody, T> {
    
        private Type mType;
    
        public FastJsonResponseBodyConvert(Type type) {
            this.mType = type;
        }
    
        @Override
        public T convert(ResponseBody value) throws IOException {
            return JSON.parseObject(value.string(), mType);
        }
    
    }
    

    5.数据返回统一处理

    public abstract class BaseObserver<T> implements Observer<Response<T>> {
    
        @Override
        public final void onNext(@NonNull Response<T> result) {
            if (result.getRet() == -1) {
                onFailure(new Exception(result.getMsg()),  result.getMsg());//该异常可以汇报服务端
            } else {
                onSuccess(result.getData());
            }
        }
    
        @Override
        public void onError(@NonNull Throwable e) {
            onFailure(e, RxExceptionUtil.exceptionHandler(e));
        }
    
    
    
        @Override
        public void onComplete() {
    
        }
    
        @Override
        public void onSubscribe(@NonNull Disposable d) {
    
        }
    
        public abstract void onSuccess(T result);
    
        public abstract void onFailure(Throwable e, String errorMsg);
    }
    

    下面加入了异常处理类

    public class RxExceptionUtil {
    
        public static String exceptionHandler(Throwable e){
            String errorMsg = "未知错误";
            if (e instanceof UnknownHostException) {
                errorMsg = "网络不可用";
            } else if (e instanceof SocketTimeoutException) {
                errorMsg = "请求网络超时";
            } else if (e instanceof HttpException) {
                HttpException httpException = (HttpException) e;
                errorMsg = convertStatusCode(httpException);
            } else if (e instanceof ParseException || e instanceof JSONException
                    || e instanceof com.alibaba.fastjson.JSONException) {
                errorMsg = "数据解析错误";
            } 
            return errorMsg;
        }
    
        private static String convertStatusCode(HttpException httpException) {
            String msg;
            if (httpException.code() >= 500 && httpException.code() < 600) {
                msg = "服务器处理请求出错";
            } else if (httpException.code() >= 400 && httpException.code() < 500) {
                msg = "服务器无法处理请求";
            } else if (httpException.code() >= 300 && httpException.code() < 400) {
                msg = "请求被重定向到其他页面";
            } else {
                msg = httpException.message();
            }
            return msg;
        }
    }
    

    6.异步请求加入Loading Dialog

    这个时候我们可以根据自己项目中统一封装的dialog自行扩展BaseObserver

    public abstract class ProgressObserver<T> extends  BaseObserver<T>{
        private MaterialDialog mMaterialDialog;
        private Context mContext;
        private String mLoadingText;
    
        public ProgressObserver(Context context){
            this(context, null);
        }
    
        public ProgressObserver(Context context, String loadingText){
            mContext = context;
            mLoadingText = loadingText;
        }
    
        @Override
        public void onSubscribe(@NonNull Disposable d) {
            if (!d.isDisposed()) {
                mMaterialDialog = new MaterialDialog.Builder(mContext).content(mLoadingText == null ? "正在加载中..."
                        : mLoadingText).isProgress(true).build();
                mMaterialDialog.show();
            }
        }
    
        @Override
        public void onComplete() {
            if (mMaterialDialog != null) {
                mMaterialDialog.dismiss();
            }
        }
    
        @Override
        public void onError(@NonNull Throwable e) {
            super.onError(e);
            if (mMaterialDialog != null) {
                mMaterialDialog.dismiss();
            }
        }
    
    }
    

    7.加入调度类,方便调用线程切换和解决内存泄漏的问题

    public class RxSchedulers {
    
        public static <T> ObservableTransformer<T, T> observableIO2Main(final Context context) {
            return upstream -> {
                Observable<T> observable = upstream.subscribeOn(Schedulers.io())
                        .observeOn(AndroidSchedulers.mainThread());
                return composeContext(context, observable);
            };
        }
    
        public static <T> ObservableTransformer<T, T> observableIO2Main(final RxFragment fragment) {
            return upstream -> upstream.subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread()).compose(fragment.<T>bindToLifecycle());
        }
    
        private static <T> ObservableSource<T> composeContext(Context context, Observable<T> observable) {
            if(context instanceof RxActivity) {
                return observable.compose(((RxActivity) context).bindUntilEvent(ActivityEvent.DESTROY));
            } else if(context instanceof RxFragmentActivity){
                return observable.compose(((RxFragmentActivity) context).bindUntilEvent(ActivityEvent.DESTROY));
            }else if(context instanceof RxAppCompatActivity){
                return observable.compose(((RxAppCompatActivity) context).bindUntilEvent(ActivityEvent.DESTROY));
            }else {
                return observable;
            }
        }
    }
    
    

    使用

    讲了那么多,那么如何使用这个封装呢?下面来看下如何使用。

    RxHttp.getInstance().getSyncServer().getLatestVersion("1", "1.0.0")
                    .compose(RxSchedulers.observableIO2Main(this))
                    .subscribe(new ProgressObserver<String>(this) {
                        @Override
                        public void onSuccess(String result) {
                            Toast.makeText(MainActivity.this, result, Toast.LENGTH_SHORT).show();
                        }
    
                        @Override
                        public void onFailure(Throwable e, String errorMsg) {
    
                        }
                    });
    

    是不是封装后的代码显得更为简洁一点呢?欢迎大佬多多指正。
    如果感兴趣可以看下github上源码github项目链接

    参考资料

    相关文章

      网友评论

      本文标题:RxJava2 Retrofit2 网络框架简洁轻便封装

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