OkHttp


OkHttp是高效的HTTP客户端
HTTP交换数据和媒体的网络方式,高效HTTP让资源加载更快,节省带宽
OkHttp默认特性
支持HTTP/2,允许所有同一个主机地址的请求共享同一个socket连接
连接池减少请求延时
透明的GZIP压缩减少响应数据的大小
缓存响应内容,避免一些完全重复的请求
当网络出现问题的时候OkHttp依然坚守自己的职责,
自动恢复一般的连接问题,如果服务有多个IP地址,当第一个IP请求失败时,OkHttp会交替尝试你配置的其他IP,
OkHttp使用现代TLS技术(SNI, ALPN)初始化新的连接,
当握手失败时会回退到TLS 1.0
OkHttp 支持 Android 2.3 及以上版本Android平台, 对于 Java, JDK 1.7及以上
OkHttp官网
//square.github.io/okhttp/
OkHttp GitHub地址:https://github.com/square/okhttp
官方介绍
HTTP/2 support allows all requests to the same host to share a socket.
Connection pooling reduces request latency (if HTTP/2 isn’t available).
Transparent GZIP shrinks download sizes.
Response caching avoids the network completely for repeat requests.
OkHttp
.支持http2(支持SPDY),允许所有请求公用一个socket。
.使用连接池减少请求延迟(不支持http2)
.透明的Gzip压缩
.用响应缓存来避免重复的网络请求
一、添加依赖和网络权限//网络请求依赖
api 'com.squareup.okhttp3:okhttp:3.10.0'
api 'com.squareup.okio:okio:1.14.0'
//添加网络权限
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
二、简单使用
1、发送GET请求
@Test
public void testGet(){    //创建OkHttpClient实例对象
    OkHttpClient okHttpClient = new OkHttpClient();   //创建Request对象
    Request request = new Request.Builder().url("https://www.h.o/get?id=111").addHeader("key","value").get().build();  //执行Request请求  //异步
      //同步请求
    try {
        Response response = okHttpClient.newCall(request).execute();
        System.out.println(response.body().string());
    } catch (IOException e) {
        e.printStackTrace();
    }
}
2、发送POST请求 与get请求的不同之处需要顶一个RequestBody
@Test
public void testPost(){   //1、创建OkHttpClient对象实例
    OkHttpClient okHttpClient = new OkHttpClient();    //2、创建Request对象
    MediaType mediaType = MediaType.parse("application/json; charset=utf-8");
    RequestBody requestBody = RequestBody.create(mediaType,"{}");
    Request request = new Request.Builder() .url("https://www.h.og/post") .post(requestBody) .build();    //3、执行Request请求
    try {
        Response response = okHttpClient.newCall(request).execute();
        System.out.println(response.body().string());
    } catch (IOException e) {
        e.printStackTrace();
    }
}
基本三步
1、创建OkHttpClient对象实例
2、创建你需要的Request对象,如果是post请求需要添加RequestBody
3、使用OkHttpClient对象实例执行请求,得到Response对象
官方的介绍
//github.com/square/okhttp/wiki/Recipes
三、添加拦截器
Application interceptors与Network Interceptors之间的区别
Each interceptor chain has relative merits.
Application interceptors
1、Don’t need to worry about intermediate responses like redirects and retries.
2、Are always invoked once, even if the HTTP response is served from the cache.
3、Observe the application’s original intent. Unconcerned with OkHttp-injected headers like If-None-Match.
4、Permitted to short-circuit and not call Chain.proceed().
5、Permitted to retry and make multiple calls to Chain.proceed().
Network Interceptors
1、Able to operate on intermediate responses like redirects and retries.
2、Not invoked for cached responses that short-circuit the network.
3、Observe the data just as it will be transmitted over the network.
4、Access to the Connection that carries the request.
Application Interceptor
不用关心redirects和reties的Response中间的过程
永远只会调用一次,不管Http Response是否是从缓存中直接取到的
可监控原始的请求,不关心其它诸如If-None-Match的Header
允许不调用Chain.proceed()
允许重试多次调用Chain.proceed()
Network Interceptors
可操作redirects和reties的过程
不会调用缓存的Response
可监控网络传输交互的数据
可获取Connection携带的请求信息
区别在于:Application Interceptor能拦截所有类型的请求,
包括缓存命中的请求;
而Network Interceptors仅拦截非WebSocket的情况下产生真正网络访问的请求。
因此在Network Interceptors上做网络上传和下载进度的监听器是比较合适的。
@Test
public void testInterceptor(){
    Interceptor loggingInterceptor = new Interceptor() {
        @Override
        public Response intercept(Chain chain) throws IOException {
            Request request = chain.request();
            Logger logger = Logger.getGlobal();
            //我这里参考的是官网的,你也可以定义里自己的打印方式
            long t1 = System.nanoTime();
            logger.info(String.format("Sending request %s on %s%n%s", request.url(), chain.connection(), request.headers()));
            Response response = chain.proceed(request);
            long t2 = System.nanoTime();
            logger.info(String.format("Received response for %s in %.1fms%n%s",response.request().url(), (t2 - t1) / 1e6d, response.headers()));
            return response;
        }
    };
    //1、创建OkHttpClient实例对象
    OkHttpClient okHttpClient = new OkHttpClient.Builder().addInterceptor(loggingInterceptor)  //.addNetworkInterceptor() // 加网络拦截器
                .build();
    //2、创建Request实例对象
    Request request = new Request.Builder().url("https://www.h.o/get?id=111").get().build();   //3、使用client执行request请求
    try {
        Response response = okHttpClient.newCall(request).execute();
        System.out.println(response.body().string());
    } catch (IOException e) {
        e.printStackTrace();
    }
}
拦截器模拟数据
public class FakeApiInterceptor implements Interceptor {
    @Override
    public Response intercept(Chain chain) throws IOException {
        Response response;
        if (BuildConfig.DEBUG && chain.request().url().toString().equals(API_URL)) {
            String json = "{\"code\": 200, \"message\": \"success\"}";
            response = new Response.Builder()
                    .code(200)
                    .addHeader("Content-Type", "application/json")
                    .body(ResponseBody.create(MediaType.parse("application/json"), json))
                    .message(json)
                    .request(chain.request())
                    .protocol(Protocol.HTTP_2)
                    .build();
        } else {
            response = chain.proceed(chain.request());
        }
        return response;
    }
}
四、添加缓存处理
@Test
public void testCache(){
    Cache cache = new Cache(new File(Environment.getDataDirectory(),"cache"),10*1024*1024);   //创建OkHttpClient实例对象
    OkHttpClient okHttpClient = new OkHttpClient.Builder().cache(cache).build();//建Request实例对象
    Request request = new Request.Builder().url("").get().build();    //用client执行Request请求
    try {
        Response response = okHttpClient.newCall(request).execute();//从缓存中获取响应
        Response cacheResponse = response.cacheResponse();//从网络中获取响应
        Response networkResponse = response.networkResponse();
        System.out.println(response.body().string());
        System.out.println(cacheResponse.body().string());
        System.out.println(networkResponse.body().string());
    } catch (IOException e) {
        e.printStackTrace();
    }
}