android:Retrofit+RxJava的优雅封装

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 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 call = service.login("张晓宇", "is sb");
        call.enqueue(new Callback() {
            @Override
            public void onResponse(Call call, Response response) {
                //请求成功
            }
            @Override
            public void onFailure(Call call, Throwable t) {
                //请求失败
            }
        });

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

Retrofit+RxJava优雅的封装

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

BaseRequestEntity.java

public class BaseRequestEntity {
    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 {
    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> login(@Body BaseRequestEntity 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 getLoginRequestEntity() {
        BaseRequestEntity 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 implements Observer> {
    protected Context mContext;

    public BaseObserver() {

    }

    public BaseObserver(Context cxt) {
        this.mContext = cxt;
    }

    @Override
    public void onSubscribe(Disposable d) {
        onRequestStart();
    }

    @Override
    public void onNext(BaseResponseEntity 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 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  ObservableTransformer observableIO2Main(final Context context) {
        return new ObservableTransformer() {
            @Override
            public ObservableSource apply(Observable upstream) {
                return upstream.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
            }
        };
    }
}

8、使用方式

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

                    @Override
                    protected void onFailure(String errorMessage) {
                        showErrorDialog(errorMessage);
                    }

                });
    }

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

你可能感兴趣的:(android:Retrofit+RxJava的优雅封装)