OkHttp3+Retrofit2+RxJava2 集成使用

OkHttp框架

Android为我们提供了两种 HTTP交互的方式:HttpURLConnectionApache HTTP Client ,虽然两者都支持HTTPS,流的上传下载,设置超时,IPv6和连接池,已足够满足我们各种HTTP请求的需求。但更高效的使用HTTP可以让我们的应用运行更快,更节省流量。因此 OkHttp库 也为此诞生。
OkHttp是一款高效的HTTP库,支持链接同一地址的链接共享一个socket通过连接池来减少响应延迟,还有透明的GZIP压缩,请求缓存等优势。OkHttp 存在以下的特点:

  • 支持 HTTP2/SPDY
  • socket自动选择最好路线,并支持自动重连
  • 拥有自动维护的socket连接池,减少握手次数
  • 拥有队列线程池,轻松写并发
  • 拥有Interceptors 轻松处理请求与响应(比如透明GZIP压缩,LOGGING)
  • 基于 Headers 的缓存策略

Retrofit2 框架

Retrofit 与 OkHttp 共同出自于 Square公司,Retrofit 是对 OkHttp做了一层封装。把网络请求都交给OkHttp,我们只需要通过简单的配置就能使用 Retrofit来进行网络请求了。Retrofit存在的优势:

  • Retrofit 使用注解方式,大大简化了我们的URL拼写形式,而且注释含义一步了然,简单易懂
  • Retrofit 使用简单,结构层次分明,每一步都能够表达出之所以要使用的寓意
  • Retrofit 支持同步和异步,使得请求变得异常的简单,只要调用 enqueue/execute 即可完成
  • Retrofit 更大自由度的支持我们自定义的业务逻辑,如 自定义 Converters

RxJava2

RxJava 主要为了实现异步,其优点就是能够让异步代码 更加简介,而且随着程序变得越来越复杂,它依然保持简洁(逻辑简洁)

具体三个框架详细的介绍,之前已经介绍过,这里就不再敖述

来个实例(请求 接口,访问数据,使用 AndroidStudio)

添加依赖

首先在build.gradle 中添加依赖

implementation 'com.squareup.okhttp3:okhttp:3.11.0' // 必要,okhttp依赖
implementation 'com.squareup.okhttp3:logging-interceptor:3.11.0' //log 拦截器
implementation 'io.reactivex.rxjava2:rxandroid:2.0.1' //必要,切换线程时用到
implementation 'io.reactivex.rxjava2:rxjava:2.1.1' //必要 rxjava 依赖
implementation 'com.squareup.retrofit2:retrofit:2.3.0' // 必要retrofit依赖
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.3.0' // 必要依赖,和Rxjava结合必须用到
implementation 'com.squareup.retrofit2:converter-gson:2.3.0' // 必要依赖,解析json字符所用
先对 OkHttp3 进行二次封装
public class okHttp3 {
    /**
     * 懒汉 安全 加同步
     * 私有的静态成员变量  只能声明,不能创建
     * 私有的构造方法
     * 提供返回实例的静态方法
     */

    private static OkHttpClient okHttpClient = null;
    private okHttp3(){}

    public static OkHttpClient getInstence(){
        if(okHttpClient == null){
            synchronized (okHttp3.class){
                if(okHttpClient == null){
                    //okHttp 可以缓存数据,指定缓存路径
                    File sdcache = new File(Environment.getExternalStorageDirectory(),"huancun");
                    //指定缓存
                    int chcheSize = 10*1024*1024;

                    //<<<<<<<<<<<<<<<<<日志显示级别>>>>>>>>>>>>>>>>>>>
                    HttpLoggingInterceptor.Level level = HttpLoggingInterceptor.Level.BODY;
                    //新建Log拦截器
                    HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
                        @Override
                        public void log(String message) {
                            LogUtil.i("mylog","OkHttp>>>>>>Message:"+message);
                        }
                    });
                    loggingInterceptor.setLevel(level);


                    okHttpClient = new OkHttpClient.Builder()
                            .connectTimeout(15, TimeUnit.SECONDS) //链接超时
                            .writeTimeout(20,TimeUnit.SECONDS) //写入超时
                            .readTimeout(20, TimeUnit.SECONDS) //读取超时
                            .addInterceptor(loggingInterceptor) //添加log 拦截器
                            .cache(new Cache(sdcache.getAbsoluteFile(), chcheSize)) //设置缓存
                            .build();
                }
            }
        }
        return okHttpClient;
    }

    /**
     * get请求方法
     * @param url
     * @param callback
     */
    public static void doGet(String url, Callback callback){
        //创建OkHttp请求对象
        OkHttpClient okHttpClient = getInstence();
        //创建Request
        Request request = new Request.Builder()
                .url(url)
                .build();
        //得到Call对象
        Call call = okHttpClient.newCall(request);
        call.enqueue(callback);
    }

    /**
     * Post 提交String
     * @param url
     * @param callback
     */
    public static void doPostToString(String url, String str, Callback callback){
        MediaType mediaType = MediaType.parse("text/x-markdown; charset=utf-8");
        Request request = new Request.Builder()
                .url(url)
                .post(RequestBody.create(mediaType, str))  //传入RequestBody对象
                .build();
        Call call = okHttpClient.newCall(request);
        call.enqueue(callback);
    }


    /**
     * Post 提交 表单信息
     * @param url
     * @param params
     * @param callback
     */
    public static void doPostToForm(String url, Map params , Callback callback){
        //创建OkHttpClient对象
        OkHttpClient okHttpClient = getInstence();
        FormBody.Builder builder = new FormBody.Builder();
        //遍历集合
        for(String key:params.keySet()){
            builder.add(key,params.get(key));
        }

        //创建Request
        Request request = new Request.Builder()
                .url(url)
                .post(builder.build())  //传入RequestBody对象
                .build();
        Call call = okHttpClient.newCall(request);
        call.enqueue(callback);

    }

    /**
     * Post 提交 流
     * @param url
     * @param str
     * @param callback
     */
    public static void doPostToIO(String url,final String str, Callback callback){
        RequestBody requestBody = new RequestBody() {
            @Nullable
            @Override
            public MediaType contentType() {
                return MediaType.parse("text/x-markdown; charset=utf-8");
            }
            @Override
            public void writeTo(BufferedSink sink) throws IOException {
                sink.writeUtf8(str);
            }
        };

        OkHttpClient okHttpClient = getInstence();
        Request request = new Request.Builder()
                .url(url)
                .post(requestBody)
                .build();
        Call call = okHttpClient.newCall(request);
        call.enqueue(callback);
    }


    /**
     * Post 提交 文件
     * @param url
     * @param f
     * @param callback
     */
    public static void doPostToFile(String url, File f, Callback callback){
        MediaType mediaType = MediaType.parse("text/x-markdown; charset=utf-8");
        OkHttpClient okHttpClient = getInstence();
        Request request = new Request.Builder()
                .url(url)
                .post(RequestBody.create(mediaType, f))
                .build();

        Call call = okHttpClient.newCall(request);
        call.enqueue(callback);
    }

}

然后对Retrofit进行封装

先针对 服务器返回的数据格式来创建JavaBean对象
BaseEntity

public class BaseEntity {
    private static int SUCCESS_CODE = 200; //成功的code
    private int code;
    private String message;
    private T result;

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

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public T getResult() {
        return result;
    }

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

obTextBean

public class obTextBean {
    private String name;
    private String desc;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getDesc() {
        return desc;
    }

    public void setDesc(String desc) {
        this.desc = desc;
    }
}

Retrofit的使用会最终生成代理对象,需要一个接口:

public interface APIFunction {
    @GET("searchAuthors")  //最终会和 Retrofit中的路径进行拼接,所以该字符串不能以 “/”开头
    @Headers("Content-Type:application/x-www-form-urlencoded; charset=utf-8") //防止乱码
    Observable>> getBaidu(@Query("name") String name); 
}

上述代码,在接口中 设置了 getBaidu的方法,使用了RxJava 框架,这样就可以通过代理对象来调用这个方法了。

对Retrofit 封装:

public class RetrofitFactory {
    private static RetrofitFactory mRetrofitFactory;
    private static APIFunction mAPIFunction;
    private RetrofitFactory(){
        OkHttpClient client = okHttp3.getInstence(); //获取上面封装的 OkHttp3 实例
        Retrofit mRetrofit = new Retrofit.Builder()
                .baseUrl("https://api.apiopen.top/")  //指定接口路径
                .addConverterFactory(GsonConverterFactory.create()) //添加Gson 转换器
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) // 添加RxJava转换器
                .client(client)  //添加OkHttp
                .build();
        mAPIFunction = mRetrofit.create(APIFunction.class); // 通过接口创建代理对象
    }

    public static RetrofitFactory getInstence(){
        if(mRetrofitFactory == null){
            synchronized (RetrofitFactory.class){
                if(mRetrofitFactory == null){
                    mRetrofitFactory = new RetrofitFactory();
                }
            }
        }
        return mRetrofitFactory;
    }

    public APIFunction API(){
        return mAPIFunction;
    }

}

使用:

RetrofitFactory.getInstance().API()
	.getBaidu("李白")
	.subscribeOn(Schedulers.io())
	.observeOn(AndroidSchedulers.mainThread())
	.subscribe(new Observer>() {
                    @Override
                    public void onSubscribe(Disposable d) {
                        
                    }
 
                    @Override
                    public void onNext(BaseEntity aBeanBaseEntity) {
 
                    }
 
                    @Override
                    public void onError(Throwable e) {
 
                    }
 
                    @Override
                    public void onComplete() {
 
                    }
                });

但是我们发现,代码还是有点重复,对于 RxJava 中线程的指定 .subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()),还有 .subscribe 中的四个重构方法,除了onNext之外, 其他的方法都是在重复出现,所以我们可以对 这两处进行封装。

首先对 指定线程封装:

/**
     * 统一线程处理(Observable)
     * @param 
     * @return
     */
    public static ObservableTransformer setIO_Obervable(){
        return new ObservableTransformer() {
            @Override
            public ObservableSource apply(Observable observable) {
                return observable.subscribeOn(Schedulers.io())
                        .observeOn(AndroidSchedulers.mainThread());
            }
        };
    }
    -----------------------或者:--------------------------------
    /**
     * 统一线程处理(Flowable)
     * @param 
     * @return
     */
    public static  FlowableTransformer setIO_Flowable() {    //compose简化线程
        return new FlowableTransformer() {
            @Override
            public Flowable apply(Flowable observable) {
                return observable.subscribeOn(Schedulers.io())
                        .observeOn(AndroidSchedulers.mainThread());
            }
        };
    }

然后对Observer进行封装:

/**
 * 对 Observer(观察者) 除 onNext方法外的其他方法的封装
 * @param 
 */
public abstract class CommonObserver implements Observer {
    private Context mContext;

    protected CommonObserver(Context context) {
        mContext = context;
    }

    @Override
    public void onSubscribe(Disposable d) {
        //这里可以显示进度条
        Dialogs.showWaitDialog(mContext,"正在访问...");
        LogUtil.i("mylog","----Observer_subscribe---");
    }

    @Override
    public abstract void onNext(T t);

    @Override
    public void onError(Throwable e) {
        //这里用来隐藏进度条或者显示错误提示
        LogUtil.i("mylog","----CommonObserverE:"+e.getMessage());
    }

    @Override
    public void onComplete() {
        //这里隐藏进度条
        Dialogs.hideWaitDialog();
        LogUtil.i("mylog","----Observer_complete---");
    }
}

最终代码如下:

RetrofitFactory.getInstence().API()
                        .getBaidu("李白")
                        .compose(RxJava2.>>setIO_Obervable())
                        .subscribe(new CommonObserver>>(this) {
                            @Override
                            public void onNext(BaseEntity> objectBaseEntity) {
                                if(objectBaseEntity.isSuccess()){
                                    ArrayList objects = objectBaseEntity.getResult();
                                    for(int i =0;i

你可能感兴趣的:(android)