使用Retrofit+RxJava实现网络请求

安卓基础开发库,让开发简单点。
DevRing & Demo地址https://github.com/LJYcoder/DevRing

学习/参考地址:
Retrofit:
整体教程 http://blog.csdn.net/jdsjlzx/article/details/52015347
文件上传 http://blog.csdn.net/jdsjlzx/article/details/52246114
文件下载 http://www.jianshu.com/p/060d55fc1c82
Https请求 http://blog.csdn.net/dd864140130/article/details/52625666
异常处理 http://blog.csdn.net/mq2553299/article/details/70244529
失败重试 http://blog.csdn.net/johnny901114/article/details/51539708
生命周期 http://android.jobbole.com/83847 | http://mp.weixin.qq.com/s/eedFDMIQe30rQmryLeif_Q

RxJava:
整体教程(RxJava1) https://gank.io/post/560e15be2dca930e00da1083
整体教程(RxJava2) https://mp.weixin.qq.com/s/UAEgdC2EtqSpEqvog0aoZQ
操作符 https://zhuanlan.zhihu.com/p/21926591
使用场景 http://blog.csdn.net/theone10211024/article/details/50435325
1.x与2.x区别 http://blog.csdn.net/qq_35064774/article/details/53045298

前言

Retrofit是目前主流的网络请求框架,功能强大,操作便捷。
RxJava是实现异步操作的库。可在线程间快速切换,同时提供许多操作符,使一些复杂的操作代码变得清晰有条理。
两者结合使用后,使得网络请求更加简洁,尤其在嵌套请求等特殊场景大有作为。

本文侧重于介绍Retrofit网络请求,以及它是如何结合RxJava使用的。还没了解过RxJava的建议先到上面贴出的参考地址学习,以便更好明白两者结合的过程。

文章篇幅较长,因为希望尽可能涵盖常用、实用的模块。

demo以及文章中的RxJava部分,已从1.x更新到2.x。


介绍

下面通过配置,请求,异常处理,生命周期管理,失败重试,封装,混淆这几个部分来介绍。

1. 配置

1.1 添加依赖

//Rxjava
compile 'io.reactivex.rxjava2:rxjava:2.1.6'
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
//Retrofit
compile 'com.squareup.retrofit2:retrofit:2.3.0'
compile 'com.squareup.retrofit2:converter-gson:2.3.0'
compile 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'
compile 'com.squareup.okhttp3:logging-interceptor:3.8.0'

1.2 开启Log日志

OkHttpClient.Builder okHttpClientBuilder = new OkHttpClient.Builder();
//启用Log日志
HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
okHttpClientBuilder.addInterceptor(loggingInterceptor);

开启后,则可以在Log日志中看到网络请求相关的信息了,如请求地址,请求状态码,返回的结果等。

Log日志截图

1.3 开启Gson转换

Retrofit.Builder retrofitBuilder = new Retrofit.Builder();
//配置转化库,采用Gson
retrofitBuilder.addConverterFactory(GsonConverterFactory.create());

开启后,会自动把请求返回的结果(json字符串)自动转化成与其结构相符的实体。

1.4 采用Rxjava

Retrofit.Builder retrofitBuilder = new Retrofit.Builder();
//配置回调库,采用RxJava
retrofitBuilder.addCallAdapterFactory(RxJava2CallAdapterFactory.create());

1.5 设置基础请求路径BaseUrl

Retrofit.Builder retrofitBuilder = new Retrofit.Builder();
//服务器地址,基础请求路径,最好以"/"结尾
retrofitBuilder.baseUrl("https://api.douban.com/");

1.6 设置请求超时

OkHttpClient.Builder okHttpClientBuilder = new OkHttpClient.Builder();
//设置请求超时时长为15秒
okHttpClientBuilder.connectTimeout(15, TimeUnit.SECONDS);

1.7 设置缓存

Interceptor cacheIntercepter=new Interceptor() {
     @Override
     public Response intercept(Chain chain) throws IOException {
         //对request的设置用来指定有网/无网下所走的方式
         //对response的设置用来指定有网/无网下的缓存时长

         Request request = chain.request();
         if (!NetworkUtil.isNetWorkAvailable(mContext)) {
             //无网络下强制使用缓存,无论缓存是否过期,此时该请求实际上不会被发送出去。
             //有网络时则根据缓存时长来决定是否发出请求
             request = request.newBuilder()
             .cacheControl(CacheControl.FORCE_CACHE).build();
         }

         Response response = chain.proceed(request);
         if (NetworkUtil.isNetWorkAvailable(mContext)) {
             //有网络情况下,超过1分钟,则重新请求,否则直接使用缓存数据
             int maxAge = 60; //缓存一分钟
             String cacheControl = "public,max-age=" + maxAge;
             //当然如果你想在有网络的情况下都直接走网络,那么只需要
             //将其超时时间maxAge设为0即可
              return response.newBuilder()
              .header("Cache-Control",cacheControl)
              .removeHeader("Pragma").build();
         } else {
             //无网络时直接取缓存数据,该缓存数据保存1周
             int maxStale = 60 * 60 * 24 * 7 * 1;  //1周
             return response.newBuilder()
             .header("Cache-Control", "public,only-if-cached,max-stale=" + maxStale)
             .removeHeader("Pragma").build();
         }

     }
 };

File cacheFile = new File(mContext.getExternalCacheDir(), "HttpCache");//缓存地址
Cache cache = new Cache(cacheFile, 1024 * 1024 * 50); //大小50Mb

//设置缓存方式、时长、地址
OkHttpClient.Builder okHttpClientBuilder = new OkHttpClient.Builder();
okHttpClientBuilder.addNetworkInterceptor(cacheIntercepter);
okHttpClientBuilder.addInterceptor(cacheIntercepter);
okHttpClientBuilder.cache(cache);

1.8 设置header

可统一设置

Interceptor headerInterceptor = new Interceptor() {
     @Override
     public Response intercept(Chain chain) throws IOException {
         Request originalRequest = chain.request();
         Request.Builder builder = originalRequest.newBuilder();
         //设置具体的header内容
         builder.header("timestamp", System.currentTimeMillis() + "");

         Request.Builder requestBuilder = 
         builder.method(originalRequest.method(), originalRequest.body());
         Request request = requestBuilder.build();
         return chain.proceed(request);
     }
 };
//设置统一的header
OkHttpClient.Builder okHttpClientBuilder = new OkHttpClient.Builder();
okHttpClientBuilder.addInterceptor(getHeaderInterceptor());

也可在请求方法中单独设置

@Headers("Cache-Control: max-age=120")
@GET("请求地址")
Observable<HttpResult> getInfo();

或者

@GET("请求地址")
Observable<HttpResult> getInfo(@Header("token") String token);

1.9 设置https访问

现在不少服务器接口采用了https的形式,所以有时就需要设置https访问。
下面列举“客户端内置证书”时的配置方法,其他方式请参考 http://blog.csdn.net/dd864140130/article/details/52625666

//设置https访问(验证证书,请把服务器给的证书文件放在R.raw文件夹下)
okHttpClientBuilder.sslSocketFactory(getSSLSocketFactory(mContext, new int[]{R.raw.tomcat}));
okHttpClientBuilder.hostnameVerifier(org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

getSSLSocketFactory()方法如下:

//设置https证书
protected static SSLSocketFactory getSSLSocketFactory(Context context, int[] certificates) {

    if (context == null) {
        throw new NullPointerException("context == null");
    }

    //CertificateFactory用来证书生成
    CertificateFactory certificateFactory;
    try {
        certificateFactory = CertificateFactory.getInstance("X.509");
        //Create a KeyStore containing our trusted CAs
        KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
        keyStore.load(null, null);

        for (int i = 0; i < certificates.length; i++) {
            //读取本地证书
            InputStream is = context.getResources().openRawResource(certificates[i]);
            keyStore.setCertificateEntry(String.valueOf(i), certificateFactory
            .generateCertificate(is));

            if (is != null) {
                is.close();
            }
        }

        //Create a TrustManager that trusts the CAs in our keyStore
        TrustManagerFactory trustManagerFactory = TrustManagerFactory
        .getInstance(TrustManagerFactory.getDefaultAlgorithm());
        trustManagerFactory.init(keyStore);

        //Create an SSLContext that uses our TrustManager
        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(
  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值