美文网首页Android开发Android开发经验谈Android技术知识
【okhttp】- 网络请求封装过程(源码分析)

【okhttp】- 网络请求封装过程(源码分析)

作者: 拔萝卜占坑 | 来源:发表于2020-03-09 17:29 被阅读0次

简介

okhttp和HttpURLConnection都是用于网络请求,但okhttp并不是在HttpURLConnection基础上进行封装的,okhttp利用socket编写的一套网络请求库。在功能上更加强大,在性能上也更加优越。同时使用也更加方便。

数据请求

  • GET
    参数直接拼接到url上,url长度有128字节限制,所以参数过多或者不想直接让别人查看到参数,可以使用POST。
String getRequst(String url) throws IOException {
     OkHttpClient client = new OkHttpClient();
     Request request = new Request.Builder()
             .url(url)
             .build();
     try (Response response = client.newCall(request).execute()) {
         return response.body().string();
     }
}
  • POST
public static Response postRequst(String url, String json) throws IOException {
     MediaType JSON = MediaType.parse("application/json; charset=utf-8");
     OkHttpClient client = new OkHttpClient();
     RequestBody body = RequestBody.create(JSON, json);
     Request request = new Request.Builder()
             .url(url)
             .post(body)
             .build();
     Response response = client.newCall(request).execute();
     return response;
}

配置组装

  • OkHttpClient
    几乎所以okhttp配置的聚合类,使用构建者模式(OkHttpClient.Builder)组装网络请求需要的配置。

    具体有那些,以及用法,会在源码分析过程中讲解。

    1. http(https)请求
      newCall(Request request)
    2. WebSocket请求
      newWebSocket(Request request, WebSocketListener listener)。
  • Request

    1. HttpUrl url
      URL结构:scheme://host:port/path?query#fragment
      scheme:通信协议,常用的有http、https、ftp、mailto等。
      host:主机域名或IP地址。
      port:端口号,可选。省略时使用协议的默认端口,如http默认端口为80。
      path:路径由零或多个"/"符号隔开的字符串组成,一般用来表示主机上的一个目录或文件地址。
      query:查询,可选。用于传递参数,可有多个参数,用"&"符号隔开,每个参数的名和值用"="符号隔开。
      fragment:信息片断字符串,也称为锚点。用于指定网络资源中的片断。
      
    2. String method
      网络请求类型:POST,GET,HEAD,DELETE,PUT,PATCH,常用的也就前两种。
    3. Headers headers
      网络请求头参数,用一个String数字保存,所以添加的时候应该是一个完整的“key:value”字符串的参数。
    4. @Nullable RequestBody body
      POST请求时,请求参数体。在发起网络请求的时候,利用sink将参数写到流里面。
    5. Map<Class<?>, Object> tags
      从源码看,就是保存实例的集合。

创建任务

  • RealCall
    持有Transmitter,Request实例。调用execute(同步)和enqueue(异步)方法,请求开始执行。
    @Override public Response execute() throws IOException {
      ...
      transmitter.timeoutEnter();
      transmitter.callStart();
      try {
        client.dispatcher().executed(this);
        return getResponseWithInterceptorChain();
      } finally {
        client.dispatcher().finished(this);
      }
    }
    
    transmitter.callStart()任务开始执行通知,client.dispatcher().executed(this)将回调加入队列。
  • Transmitter
    任务事件发射器,注册EventListener事件接收器,接受任务开始,释放等事件。持有OkHttpClient,Request等实例。
  • Dispatcher
    任务调度器,持有RealCall等对象。里面有readyAsyncCalls(将要运行的回调),runningAsyncCalls(正在运行的异步回调),runningSyncCalls(正在运行的同步回调)三个双端队列。

执行任务

okhttp使用拦截器链式调用完成网络请求,不同的拦截器完成不同的功能,同时我们可以自定义自己的拦截器,完成特定的功能。

OkHttpClient.Builder提供了两个方法添加自定义拦截器。至于区别,在后面使用到的时候讲解。

  1. addInterceptor
    保存在interceptors对象集合里
  2. addNetworkInterceptor
    保存在networkInterceptors对象集合里
拦截器

开始执行任务

Response response = chain.proceed(originalRequest);

getResponseWithInterceptorChain方法中创建很多任务拦截器,通过链式调用,直到所有拦截器执行完成。首先看一下这个方法里面拦截器添加顺序。
interceptors自定义拦截器 -> RetryAndFollowUpInterceptor -> BridgeInterceptor -> CacheInterceptor -> ConnectInterceptor -> networkInterceptors -> CallServerInterceptor。那么执行的顺序也相同。

RealInterceptorChain,持有所以的拦截器数组,原始的Request,Transmitter等,在proceed方法中调用拦截器中的intercept方法,并创建一个新RealInterceptorChain对象传递给拦截器。

  • RetryAndFollowUpInterceptor
    网络请求重试拦截器。
  • BridgeInterceptor
    配置cookie信息,以及一些头信息配置。
  • CacheInterceptor
    缓存拦截器。
  • ConnectInterceptor
    网络链接拦截器,这个是整个框架的核心。
  • CallServerInterceptor
    最后一个拦截器,大概作用就是网络请求最后,通知一些信息给服务器。

返回结果

等所有拦截器执行完成,请求结果从最后一个拦截器依次返回。

相关文章

网友评论

    本文标题:【okhttp】- 网络请求封装过程(源码分析)

    本文链接:https://www.haomeiwen.com/subject/ftimoqtx.html