美文网首页Android技术知识
Retrofit2源码学习之流程详解

Retrofit2源码学习之流程详解

作者: 辰静暮夕 | 来源:发表于2017-06-02 15:15 被阅读0次

    综述

    Retrofit到一个实际请求/响应的过程包括

    • 创建ServiceMethod,调用ServiceMethod.build()
    • 调用OkHttpCall(ServiceMethod,args)创建OkHttpCall对象,
    • 调用 CallAdapter.adapt(okHttpCall)创建关联执行器Executor和Call的应用层Call类,Android默认为ExecutorCallbackCall

    源码研究

    • 创建ServiceMethod

    ServiceMethod.build()

      public ServiceMethod build() {
          //通过Retrofit.nextCallAdapter获取callAdapter,有自定义就用自定义,没有就用默认ExecutorCallAdapterFactory
          callAdapter = createCallAdapter();
          responseType = callAdapter.responseType();
          //返回类型验证
          if (responseType == Response.class || responseType == okhttp3.Response.class) {
            throw methodError("'"
                + Utils.getRawType(responseType).getName()
                + "' is not a valid response body type. Did you mean ResponseBody?");
          }
          //通过Retrofit.nextResponseBodyConverter处理转换异常,获得自定义转换器
          responseConverter = createResponseConverter();
          //解析自定义的注解成URL组件
          for (Annotation annotation : methodAnnotations) {
            parseMethodAnnotation(annotation);
          }
    
          //错误处理
          ...
          //构建参数替换的辅助数组parameterHandlers
          int parameterCount = parameterAnnotationsArray.length;
          parameterHandlers = new ParameterHandler<?>[parameterCount];
          for (int p = 0; p < parameterCount; p++) {
            Type parameterType = parameterTypes[p];
            if (Utils.hasUnresolvableType(parameterType)) {
              throw parameterError(p, "Parameter type must not include a type variable or wildcard: %s",
                  parameterType);
            }
    
            Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
            if (parameterAnnotations == null) {
              throw parameterError(p, "No Retrofit annotation found.");
            }
            
            parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
          }
          //错误处理
         ...
          return new ServiceMethod<>(this);
        }
    
    • 用户调用enqueue方法发起异步请求

    ExecutorCallbackCall.enqueue()

        @Override public void enqueue(final Callback<T> callback) {
          checkNotNull(callback, "callback == null");
          //调用OkhttpCall的enqueue方法,Executor执行响应结果
          delegate.enqueue(new Callback<T>() {
            
            }
          });
        }
    

    OkHttpCall. enqueue

     @Override public void enqueue(final Callback<T> callback) {
        checkNotNull(callback, "callback == null");
    
        okhttp3.Call call;
        Throwable failure;
    
        synchronized (this) {
              ...
              //这里创建请求报文获得realCall
              call = rawCall = createRawCall();
               ...
        }
        //realCall发起异步请求
        call.enqueue(new okhttp3.Callback() {
               ...
              //转换响应报文
              response = parseResponse(rawResponse);
              ...
       
        });
      }
    

    createRawCall

      private okhttp3.Call createRawCall() throws IOException {
        //创建request报文
        Request request = serviceMethod.toRequest(args);
        //获得okhttp.realCall
        okhttp3.Call call = serviceMethod.callFactory.newCall(request);
        if (call == null) {
          throw new NullPointerException("Call.Factory returned null.");
        }
        return call;
      }
    

    serviceMethod.toRequest(args)

      Request toRequest(@Nullable Object... args) throws IOException {
        RequestBuilder requestBuilder = new RequestBuilder(httpMethod, baseUrl, relativeUrl, headers,
            contentType, hasBody, isFormEncoded, isMultipart);
        ...
        @SuppressWarnings("unchecked") // It is an error to invoke a method with the wrong arg types.
        ParameterHandler<Object>[] handlers = (ParameterHandler<Object>[]) parameterHandlers;
        //根据先前的parameterHandlers进行参数转换
        for (int p = 0; p < argumentCount; p++) {
          handlers[p].apply(requestBuilder, args[p]);
        }
        //创建request报文
        return requestBuilder.build();
      }
    

    parseResponse

     Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
        ResponseBody rawBody = rawResponse.body();
        //异常处理,200-299成功状态码,204和205没有响应body
       ...
          //serviceMethod.toResponse用户转换器转换
          T body = serviceMethod.toResponse(catchingBody);
          return Response.success(body, rawResponse);
    
      }
    

    总结

    通过梳理大体了解的Retrofit的整体结构和流程,当然还有很多的细节没有讨论,需要时可以查看相应的源码。
    Retrofit源码本身并不复杂,但是Retrofit的架构设计,解耦所透露的架构经验,思想,规范等是非常值得我们学习和参照设计的。

    相关文章

      网友评论

        本文标题:Retrofit2源码学习之流程详解

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