美文网首页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