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