zoukankan      html  css  js  c++  java
  • okhttp

    OkHttp 封装了请求和缓存和缓存

    OkHttp是一个相对成熟的解决方案,据说Android4.4的源码中可以看到HttpURLConnection已经替换成OkHttp实现了。所以我们更有理由相信OkHttp的强大。

    OkHttp 处理了很多网络疑难杂症:会从很多常用的连接问题中自动恢复。如果您的服务器配置了多个IP地址,当第一个IP连接失败的时候,OkHttp会自动尝试下一个IP。OkHttp还处理了代理服务器问题和SSL握手失败问题。

    使用 OkHttp 无需重写您程序中的网络代码。OkHttp实现了几乎和HttpURLConnection一样的API。如果你用了 Apache HttpClient,则OkHttp也提供了一个对应的okhttp-apache 模块。

    OkHttp 和 fresco  retrofit 等第三方库能很好的衔接。

    Okhttp作为HTTP引擎,retrofit作为restful业务架构实现;目前retrofit的restful风格规范是趋势。

    OkHttp是一个高效的Http客户端

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

    注:什么是SPDY

    SPDY(读作“SPeeDY”)是Google开发的基于TCP的传输层协议,用以最小化网络延迟,提升网络速度,优化用户的网络使用体验。SPDY并不是一种用于替代HTTP的协议,而是对HTTP协议的增强。新协议的功能包括数据流的多路复用、请求优先级以及HTTP报头压缩。谷歌表示,引入SPDY协议后,在实验室测试中页面加载速度比原先快64%。中文名:spdy协议,目前SPDY已经被Http/2代替,google已经宣布要移除SPDY;

    主要对象

    • Connections: 对JDK中的socket进行了引用计数封装,用来控制socket连接
    • Streams: 维护HTTP的流,用来对Requset/Response进行IO操作
    • Calls: HTTP请求任务封装
    • StreamAllocation: 用来控制Connections/Streams的资源分配与释放

    工作流程的概述

    当我们用OkHttpClient.newCall(request)进行execute/enenqueue时,实际是将请求Call放到了Dispatcher中,okhttp使用Dispatcher进行线程分发,它有两种方法,一个是普通的同步单线程;另一种是使用了队列进行并发任务的分发(Dispatch)与回调,我们下面主要分析第二种,也就是队列这种情况,这也是okhttp能够竞争过其它库的核心功能之一; 

    Socket管理(StreamAllocation)

    经过上一步的分配,我们现在需要进行连接了。我们目前有封装好的Request,而进行HTTP连接需要进行Socket握手,Socket握手的前提是根据域名或代理确定Socket的ip与端口。这个环节主要讲了http的握手过程与连接池的管理,分析的对象主要是StreamAllocation。

    Githug:  https://github.com/square/okhttp

    wiki:https://github.com/square/okhttp/wiki

    中文翻译wiki

    OKHttp源码解析

    配置方法:

    注意:okhttp内部依赖okio,别忘了同时导入okio

    (1)Android Studio:

    1 compile 'com.squareup.okhttp:okhttp:2.4.0'

    导入okio:

    1 compile 'com.squareup.okio:okio:1.5.0'

    (2)Eclipse:

    可以下载最新的jar okhttp he latest JAR ,添加依赖就可以用了

    最新的jar地址:okio the latest JAR

    使用:

    1 //创建okHttpClient对象
    2 OkHttpClient mOkHttpClient = new OkHttpClient();
    3 // 创建Request.Builder  post请求方式
    4 Request.Builder builder = new Request.Builder().post()
    5                 .url("https://github.com/hongyangAndroid");
    6 //创建一个Request
    7 final Request request = builder.build();
    8 //通过请求request,构造出call
    9 Call call = mOkHttpClient.newCall(request); 

    (1)Request.Builder

    通过Request.Builder设置更多的参数比如:

    (1) 添加请求头header:

    如果它本身存在值,在添加新的value之前,他们会被移除。使用addHeader(name, value)来添加头部不需要移除当前存在的headers。

    1 builder.addHeader("SYSVERSION",  "1.01");

    当写请求头,构造时用header(name, value)来为唯一出现的name设置value。

    1 Request.Builder builder = new Request.Builder().post()
    2                  .url("https://github.com/hongyangAndroid")
    3                  .header("Cookie", "OkHttpUser");

    (2)添加method

    请求携带参数:

    post方式:

    发布表单参数

     1 String url = url;
     2 // 创建builder
     3 FormBody.Builder builder = new FormBody.Builder();
     4 requestBody.add("user", "charles");
     5 requestBody.add("age", "12");
     6 // 创建RequestBody
     7 RequestBody requestBody = builder.build();
     8 
     9 Request request = new Request.Builder().post(requestBody ).url(url).build();
    10 Response response = mOKHttpClient.newCall(request).execute();

    发布multipart请求

    MultipartBody.Builder可以构建与HTML文件上传表单兼容的复杂请求主体。例如文件上传

    视频类:MediaType.parse("application/octet-stream")

     1 File file = new File(Environment.getExternalStorageDirectory(), "about.jpg");
     2 
     3 RequestBody fileBody = RequestBody.create(MediaType.parse("image/png"), file);
     4 
     5 RequestBody requestBody = new MultipartBuilder()
     6      .type(MultipartBuilder.FORM)
     7      .addPart(Headers.of(
     8           "Content-Disposition", 
     9               "form-data; name="username""), 
    10           RequestBody.create(null, "charles"))
    11      .addPart(Headers.of(
    12          "Content-Disposition", 
    13          "form-data; name="imagefile"; 
    14          filename="aboutApp.jpg""), fileBody)
    15      .build();
    16 
    17 Request request = new Request.Builder()
    18     .url("http://.../fileUpload")
    19     .post(requestBody)
    20     .build();
    21 
    22 Reponse reponse = mOkHttpClient.newCall(request).execute();

    get方式:

    1 String url = url + "?" + "user=charles" + "&age=12" 
    2 Request request = new Request.Builder().get().url(url).build();
    3 Response response = mOKHttpClient.newCall(request).execute();

    执行call:

    (1)异步

    调用call.enqueue,将call加入调度队列,等待任务执行完成,在Callback中即可得到结果。

     1 // 异步执行call
     2 call.enqueue(new Callback()
     3         {
     4             @Override
     5             public void onFailure(Request request, IOException e)
     6             {
     7             }
     8 
     9             @Override
    10             public void onResponse(final Response response) throws IOException
    11             {
    12                  String htmlStr =  response.body().string();// 当前线程不是ui线程
    13             }
    14         });  

    (2)同步,阻塞方式:

    1 Response response = call.execute();

    Response:

    (1)返回字符串,通过response.body().string()获取;

    (2)返回二进制字节数组,通过response.body().bytes()获取

    (3)返回inputStream,通过response.body().byteStream()获取 (支持大文件下载);

  • 相关阅读:
    MySQL详细操作
    啥是SQL?
    MySQL之中文乱码问题
    Windows压缩包安装MySQL
    GIL(全局解释器锁)
    协程
    线程
    第八周 编程作业
    PCA
    第八周 第一部分
  • 原文地址:https://www.cnblogs.com/CharlesGrant/p/6512712.html
Copyright © 2011-2022 走看看