美文网首页程序员Android开发经验谈安卓
android:Retrofit+RxJava的优雅封装

android:Retrofit+RxJava的优雅封装

作者: 江左灬梅郎 | 来源:发表于2018-11-26 15:19 被阅读17次
    image.png

    前言

    RetrofitRxJava已经出来很久了,很多前辈写了很多不错的文章,在此不得不感谢这些前辈无私奉献的开源精神,能让我们站在巨人的肩膀上望得更远。

    Retrofit:Retrofit是Square 公司开发的一款针对Android 网络请求的框架。
    RxJava:RxJava 是一个链式调用的异步框架。

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

    一言以辟之,就是让异步操作变得非常简单。
    各自职责:Retrofit 负责请求的数据和请求的结果,使用接口的方式呈现,OkHttp 负责请求的过程,RxJava 负责异步,各种线程之间的切换。

    RxJava的使用参考-->给 Android 开发者的 RxJava 详解
    Retrofit的使用参考-->Android Retrofit 2.0使用

    本文内容是基于Retrofit + RxJava做的一些优雅的封装。参考了很多文章加入了一些自己的理解,请多指教。


    先引入依赖

    build.gradle

        // Okhttp库
        implementation 'com.squareup.okhttp3:okhttp:3.11.0'
        implementation 'com.squareup.okhttp3:logging-interceptor:3.8.1'
        // Retrofit库
        implementation 'com.squareup.retrofit2:retrofit:2.1.0'
        implementation 'com.squareup.retrofit2:adapter-rxjava2:2.2.0'
        //RxJava
        implementation 'io.reactivex.rxjava2:rxjava:2.0.1'
        implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'
    

    在此之前,

    先来聊聊简单使用,(优雅封装见下文)

    1、先写一个接口Service
    interface APIService {
        @GET("user/login" )
        Call<UserInfo> login(@Query("username") String username,@Query("password")String password);
    }
    
    2、获取Call执行网络请求
    Retrofit retrofit = new Retrofit.Builder()
                    .addConverterFactory(GsonConverterFactory.create())
                    .baseUrl(BASE_URL)
                    .build();
            APIService service = retrofit.create(APIService.class);
    
            Call<UserInfo> call = service.login("张晓宇", "is sb");
            call.enqueue(new Callback<UserInfo>() {
                @Override
                public void onResponse(Call<UserInfo> call, Response<UserInfo> response) {
                    //请求成功
                }
                @Override
                public void onFailure(Call<UserInfo> call, Throwable t) {
                    //请求失败
                }
            });
    

    以上就是Retrofit的简单使用。但是实际项目中,我们肯定不会这么写,这样写完全不符合我们写代码的优雅性和简洁性。所以,我们要对它进行优雅的封装。

    Retrofit+RxJava优雅的封装

    1、请求实体类与返回实体类的封装

    BaseRequestEntity.java

    public class BaseRequestEntity <T>{
        private HeaderEntity header;
        private T data;
    
        public HeaderEntity getHeader() {
            return header;
        }
    
        public void setHeader(HeaderEntity header) {
            this.header = header;
        }
    
        public T getData() {
            return data;
        }
    
        public void setData(T data) {
            this.data = data;
        }
    }
    

    BaseResponseEntity.java

    public class BaseResponseEntity<T> {
        private int errorCode;
        private String errorMsg;
        private T data;
    
        public int getErrorCode() {
            return errorCode;
        }
    
        public void setErrorCode(int errorCode) {
            this.errorCode = errorCode;
        }
    
        public String getErrorMsg() {
            return errorMsg;
        }
    
        public void setErrorMsg(String errorMsg) {
            this.errorMsg = errorMsg;
        }
    
        public T getData() {
            return data;
        }
    
        public void setData(T data) {
            this.data = data;
        }
    }
    

    2、请求接口服务类封装

    ObservableAPI.java

    /**
     * 接口服务
     **/
    public interface ObservableAPI {
    
        /**
         * 登录
         */
        @POST(URL.URL_LOGIN)
        Observable<BaseResponseEntity<LoginResponseEntity>> login(@Body BaseRequestEntity<LoginRequestEntity> requestEntity);
    
    }
    

    3、ObservableManager封装(请求接口传参封装)

    ObservableManager.java

    public class ObservableManager {
    
        private static class SingletonHolder {
            static final ObservableManager INSTANCE = new ObservableManager();
        }
    
        public static ObservableManager getInstance() {
            return ObservableManager.SingletonHolder.INSTANCE;
        }
    
        /**
         * login
         */
        public BaseRequestEntity<LoginRequestEntityl> getLoginRequestEntity() {
            BaseRequestEntity<LoginRequestEntity> requestModel = new BaseRequestEntity<>();
            requestModel.setHeader(HeaderUtils.setHeaderModel());
            LoginRequestEntity loginRequestModel = new LoginRequestEntity();
            requestModel.setData(loginRequestModel);
            return requestModel;
        }
    
    }
    
    

    4、Retrofit封装

    RetrofitHandler.java

    public class RetrofitHandler {
        private static Retrofit mRetrofit;
        private static OkHttpClient mOkHttpClient;
        private static RetrofitHandler mRetrofitHandler;
        private static ObservableAPI mObservableAPI;
    
        private RetrofitHandler() {
            initRetrofit();
        }
    
        public static synchronized RetrofitHandler getInstance() {
            if (mRetrofitHandler == null) {
                synchronized (RetrofitHandler.class) {
                    if (mRetrofitHandler == null) {
                        mRetrofitHandler = new RetrofitHandler();
                    }
                }
            }
            return mRetrofitHandler;
        }
    
        /**
         * 获取 Retrofit
         */
        private void initRetrofit() {
            initOkHttpClient();
            mRetrofit = new Retrofit.Builder()
                    .baseUrl(URL.BASE_URL)
                    //JSON转换器,使用Gson来转换
                    .addConverterFactory(GsonConverterFactory.create())
                    //RxJava适配器
                    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                    .client(mOkHttpClient)
                    .build();
            mObservableAPI = mRetrofit.create(ObservableAPI.class);
        }
    
        /**
         * 单例模式获取 OkHttpClient
         */
        private static void initOkHttpClient() {
            if (mOkHttpClient == null) {
                synchronized (RetrofitHandler.class) {
                    if (mOkHttpClient == null) {
                        // 指定缓存路径,缓存大小100Mb
                        Cache cache = new Cache(new File(HttpConfig.DIR_CACHE_FILE, "HttpCache"),
                                1024 * 1024 * 100);
                        mOkHttpClient = new OkHttpClient.Builder()
                                //设置连接超时时间
                                .connectTimeout(HttpConfig.HTTP_TIME_OUT_TIME, TimeUnit.SECONDS)
                                //设置读取超时时间
                                .readTimeout(HttpConfig.HTTP_TIME_OUT_TIME, TimeUnit.SECONDS)
                                //设置写入超时时间
                                .writeTimeout(HttpConfig.HTTP_TIME_OUT_TIME, TimeUnit.SECONDS)
                                //默认重试一次
                                .retryOnConnectionFailure(true)
                                //添加请求头拦截器
                                .addInterceptor(InterceptorHelper.getHeaderInterceptor())
                                //添加日志拦截器
                                .addInterceptor(InterceptorHelper.getLogInterceptor())
                                //添加缓存拦截器
                                .addInterceptor(InterceptorHelper.getCacheInterceptor())
                                //添加重试拦截器
                                .addInterceptor(InterceptorHelper.getRetryInterceptor())
                                // 信任Https,忽略Https证书验证
                                // https认证,如果要使用https且为自定义证书 可以去掉这两行注释,并自行配制证书。
                                .sslSocketFactory(SSLSocketTrust.getSSLSocketFactory())
                                .hostnameVerifier(SSLSocketTrust.getHostnameVerifier())
                                //缓存
                                .cache(cache)
                                .build();
                    }
                }
            }
        }
    
        /**
         * 对外提供调用 API的接口
         *
         * @return
         */
        public ObservableAPI getAPIService() {
            return mObservableAPI;
        }
    }
    

    5、拦截器封装(请求头拦截器、日志拦截器、缓存拦截器、重试拦截器等)

    InterceptorHelper.java

    /**
     * @author wy
     * @description 拦截器工具类
     */
    
    public class InterceptorHelper {
        public static String TAG = "Interceptor";
    
        /**
         * 日志拦截器
         */
        public static HttpLoggingInterceptor getLogInterceptor() {
            return new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
                @Override
                public void log(String message) {
                    Log.w(TAG, "LogInterceptor---------: " + message);
                }
            }).setLevel(HttpLoggingInterceptor.Level.BODY);//设置打印数据的级别
        }
    
        /**
         * 缓存拦截器
         *
         * @return
         */
        public static Interceptor getCacheInterceptor() {
            return new Interceptor() {
                @Override
                public Response intercept(Chain chain) throws IOException {
                    Request request = chain.request();
                    //CONTEXT不能为空
                    if (!NetworkUtils.isConnected(PalApplication.getInstance().getApplicationContext())) {
                        int maxStale = 4 * 7 * 24 * 60; // 离线时缓存保存4周,单位:秒
                        CacheControl tempCacheControl = new CacheControl.Builder()
                                .onlyIfCached()
                                .maxStale(maxStale, TimeUnit.SECONDS)
                                .build();
                        request = request.newBuilder()
                                .cacheControl(tempCacheControl)
                                .build();
                    }
                    return chain.proceed(request);
                }
            };
        }
    
    
        /**
         * 重试拦截器
         *
         * @return
         */
        public static Interceptor getRetryInterceptor() {
            return new Interceptor() {
                @Override
                public Response intercept(Chain chain) throws IOException {
                    int maxRetry = 10;//最大重试次数
                    int retryNum = 5;//假如设置为3次重试的话,则最大可能请求4次(默认1次+3次重试)
    
                    Request request = chain.request();
                    Response response = chain.proceed(request);
                    while (!response.isSuccessful() && retryNum < maxRetry) {
                        retryNum++;
                        response = chain.proceed(request);
                    }
                    return response;
                }
            };
        }
    
        /**
         * 请求头拦截器
         *
         * @return
         */
        public static Interceptor getHeaderInterceptor() {
            return new Interceptor() {
                @Override
                public Response intercept(Chain chain) throws IOException {
                    //在这里你可以做一些想做的事,比如token失效时,重新获取token
                    //或者添加header等等
    
    
                    Request originalRequest = chain.request();
    
                    if (null == originalRequest.body()) {
                        return chain.proceed(originalRequest);
                    }
    
                    Request compressedRequest = originalRequest.newBuilder()
                            .header("Content-Encoding", "gzip")
                            .header("User-Agent", "OkHttp Headers.java")
                            .addHeader("Accept", "application/json; q=0.5")
                            .addHeader("Accept", "application/vnd.github.v3+json")
                            .addHeader("Accept-Encoding", "identity")
    //                    .addHeader(Constants.WEB_TOKEN, webi_token)
                            .build();
                    Response proceed = chain.proceed(compressedRequest);
                    return proceed;
                }
            };
    
        }
    }
    
    

    6、BaseObserver封装(请求失败、网络异常、接口错误、加载窗口等处理)

    BaseObserver.java

    
    public abstract class BaseObserver<T> implements Observer<BaseResponseEntity<T>> {
        protected Context mContext;
    
        public BaseObserver() {
    
        }
    
        public BaseObserver(Context cxt) {
            this.mContext = cxt;
        }
    
        @Override
        public void onSubscribe(Disposable d) {
            onRequestStart();
        }
    
        @Override
        public void onNext(BaseResponseEntity<T> tBaseEntity) {
            onRequestEnd();
            String message_common = "Oops, something went wrong. Please try again.";
            if (tBaseEntity.getErrorCode()==0) {//成功
                try {
                    onSuccess(tBaseEntity);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            } else {
                try {
                    if (!CommonUtils.isEmptyOrNull(tBaseEntity.getErrorMsg())) {
                        onFailure(tBaseEntity.getErrorMsg());
                    } else {
                        onFailure(message_common);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    
        @Override
        public void onError(Throwable e) {
            onRequestEnd();
            String message_common = "Oops, something went wrong. Please try again.";
            String msg_timeout = "Oops, connection timeout, please try again later";
            try {
                if (e instanceof ConnectException
                        || e instanceof TimeoutException
                        || e instanceof NetworkErrorException
                        || e instanceof UnknownHostException) {
                    onFailure(msg_timeout);
                } else {
                    onFailure(message_common);
                }
            } catch (Exception e1) {
                e1.printStackTrace();
            }
        }
    
        @Override
        public void onComplete() {
    
        }
    
        /**
         * 返回成功
         *
         * @param tBaseEntity
         */
        protected abstract void onSuccess(BaseResponseEntity<T> tBaseEntity);
    
        /**
         * 返回失败
         *
         * @param errorMessage
         */
        protected abstract void onFailure(String errorMessage);
    
        /**
         * 请求开始
         */
        protected void onRequestStart() {
            showProgressDialog();
        }
    
    
        /**
         * 请求结束
         */
        protected void onRequestEnd() {
            closeProgressDialog();
        }
    
        /**
         * 加载弹窗
         */
        public void showProgressDialog() {
    
        }
    
        /**
         * 关闭加载弹窗
         */
        public void closeProgressDialog() {
    
        }
    
    }
    

    7、调度类封装

    RxTransformerHelper.java

    /**
     * 调度类
     */
    public class RxTransformerHelper {
    
        public static <T> ObservableTransformer<T, T> observableIO2Main(final Context context) {
            return new ObservableTransformer<T, T>() {
                @Override
                public ObservableSource<T> apply(Observable<T> upstream) {
                    return upstream.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
                }
            };
        }
    }
    
    

    8、使用方式

    private void login() {
            RetrofitHandler.getInstance().getAPIService()
                    .login(ObservableManager.getInstance().getLoginRequestEntity())
                    .compose(RxTransformerHelper.<BaseResponseEntity<LoginResponseEntity>>observableIO2Main(this))
                    .subscribe(new BaseObserver<LoginResponseEntity>() {
                        @Override
                        protected void onSuccess(BaseResponseEntity<LoginResponseEntity> responseEntity) {
                            showSuccessDialog("Success");
                        }
    
                        @Override
                        protected void onFailure(String errorMessage) {
                            showErrorDialog(errorMessage);
                        }
    
                    });
        }
    

    9、到这里,Retrofit+RxJava基本算是优雅的封装完成了,其实,如果追求更完美的话,还可以进行二次封装,将第八步的请求封装的更为简洁。这个,就看各人喜好而定了,本文不再赘述。

    相关文章

      网友评论

        本文标题:android:Retrofit+RxJava的优雅封装

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