Retrofit2源码分析

Retrofit源码分析基于2.4.0。

关于Retrofit的基本使用可以参照 Retrofit官网

Retrofit是Java及Android平台上类型安全的Http客户端。这是官方给出关于Retrofit的简介。

这里需要明确:Retrofit只是一个Http网络请求封装库,该库的主要工作是对网络请求进行封装,最终实现网络请求的操作是由Okhttp完成的。

基本使用

使用Retrofit发起一次网络请求,只需要以下流程即可:
1. 定义一个网络请求接口。
2. 创建Retrofit实例
3. 通过Retrofit创建网络请求接口的动态代理类
4. 通过动态代理类获取Call对象,用于网络请求
5. 通过Call对象实现网络请求(同步/异步)

代码演示:

1、定义一个网络请求接口实现用户登录功能

public interface ILoginService {

    @POST("user/login")
    Call<User> Login(@Body User user);
}

2、通过Retrofit完成网络请求

// 2、创建一个Retrofit对象
Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("http://localhost:8080/testRetrofit/")
        .addConverterFactory(GsonConverterFactory.create())
        .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
        .build();

// 3、通过Retrofit创建Retrofit的代理实例
ILoginService loginService = retrofit.create(ILoginService.class);


User user = new User();
user.setUsername("jack");
user.setPassword("123456");
// 4、获取实现网络请求的Call对象
Call<User> call = loginService.login(user);

// 5、实现异步网络请求
call.enqueue(new Callback<User>() {
    @Override
    public void onResponse(Call<User> call, Response<User> response) {
        // 获取用户信息
        User body = response.body();
    }

    @Override
    public void onFailure(Call<User> call, Throwable t) {

    }
});
        // 5、同步请求获取响应
//        Response<User> execute = call.execute();
//        User body = execute.body();

源码分析

针对上文中提到的Retrofit的使用流程,这里将对这些流程的源码逐一分析。

创建Retrofit实例

Retrofit实例的创建主要是通过内部类Retrofit.Buidler实现的。很明显,这里使用了建造者模式。

这里看下Builder的构造方法:

    Builder(Platform platform) {
      this.platform = platform;
    }

    public Builder() {
      this(Platform.get());
    }

    Builder(Retrofit retrofit) {
      platform = Platform.get();
      callFactory = retrofit.callFactory;
      baseUrl = retrofit.baseUrl;

      converterFactories.addAll(retrofit.converterFactories);
      // Remove the default BuiltInConverters instance added by build().
      converterFactories.remove(0);

      callAdapterFactories.addAll(retrofit.callAdapterFactories);
      // Remove the default, platform-aware call adapter added by build().
      callAdapterFactories.remove(callAdapterFactories.size() - 1);

      callbackExecutor = retrofit.callbackExecutor;
      validateEagerly = retrofit.validateEagerly;
    }

从源码可知,Retrofit有三个构造方法,但是两个具有包级访问权限,所以外部能使用的就只有无参数构造方法。

这种构造方法的设计和Okhttp是相同的。

在上面的无参构造方法中,内部通过Platform.get()方法获取一个Platform实例以完成Retrofit的创建。

Platform将在下章节中通CallAdapter一同讲解,这里只需要知道在Android平台中该Platform的作用就是提供一个CallAdapter工厂用于创建CallAdapter即可。

接着看下Builder.build()方法,build()方法主要是对Retrofit中一些属性做初始化操作。

Retrofit声明的属性

 private final Map<Method, ServiceMethod<?, ?>> serviceMethodCache = new ConcurrentHashMap<>();

  final okhttp3.Call.Factory callFactory;
  final HttpUrl baseUrl;
  final List<Converter.Factory> converterFactories;
  final List<CallAdapter.Factory> callAdapterFactories;
  final @Nullable Executor callbackExecutor;
  final boolean validateEagerly;

build()方法:

public Retrofit build() {

      // 设置baseUrl,必填
      if (baseUrl == null) {
        throw new IllegalStateException("Base URL required.");
      }

      // 设置callFactory,用于创建Call实例,这里默认使用的是OkHttpClient
      // 所以通过这里可以看出
      okhttp3.Call.Factory callFactory = this.callFactory;
      if (callFactory == null) {
        callFactory = new OkHttpClient();
      }

      // 设置异步回调请求执行器,没有设置就使用默认的,在Platform.Android下默认返回主线程(UI线程)执行器
      // 主要在异步请求中会使用到
      Executor callbackExecutor = this.callbackExecutor;
      if (callbackExecutor == null) {
        callbackExecutor = platform.defaultCallbackExecutor();
      }


      // 创建CallAdapter集合,用于存放所有的callAdapter网络请求适配器
      List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
      callAdapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));

      // 创建数据解析器。gson、jaskson等
      List<Converter.Factory> converterFactories =
          new ArrayList<>(1 + this.converterFactories.size());
      // 首先会添加一个默认的BuiltInConverters
      converterFactories.add(new BuiltInConverters());
      converterFactories.addAll(this.converterFactories);

      // 创建Retrofit实例
      return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
          unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
    }

其实,build()方法中主要就是完成了Retrofit的一些配置,这个从最后Retrofit的构造方法中可以看出。

设置baseUrl

在Retrofit实例的创建中,baseUrl为必填属性,这里我们看下Builder.baseUrl()的实现。

public Builder baseUrl(String baseUrl) {
  // 非空判断
  checkNotNull(baseUrl, "baseUrl == null");
  // 根据传入的url生成一个HttpUrl对象,这个类主要是对http的url做一些封装
  HttpUrl httpUrl = HttpUrl.parse(baseUrl);
  if (httpUrl == null) {
    throw new IllegalArgumentException("Illegal URL: " + baseUrl);
  }
  return baseUrl(httpUrl);
}

public Builder baseUrl(HttpUrl baseUrl) {

  checkNotNull(baseUrl, "baseUrl == null");
  // 下面整个逻辑判断传入的url是否是以"/"结尾
  List<String> pathSegments = baseUrl.pathSegments();
  if (!"".equals(pathSegments.get(pathSegments.size() - 1))) {
    throw new IllegalArgumentException("baseUrl must end in /: " + baseUrl);
  }
  this.baseUrl = baseUrl;
  return this;
}

在上面baseUrl()方法中可知,url必须要以“/”结尾,这个也是在使用Retrofit中必须要注意的一点。

创建网络接口代理类

在Retrofit.create()中主要使用到了Java动态代理,如果对动态代理的实现机制不清楚的话,请自行学习,这里就不对动态代理做深入分析了。

在完成了Retrofit实例的创建后,就要通过Retrofit.create()方法创建一个网络请求代理类,这个类根据定义的网络请求接口生成。

ILoginService loginService = retrofit.create(ILoginService.class);

这里看下Retrofit.create()方法的具体实现:

  public <T> T create(final Class<T> service) {

    // 1、首先判断类service是不是一个接口
    Utils.validateServiceInterface(service);
    // 2、validateEagerly默认是false
    if (validateEagerly) {
      // 3、提前加载method,这个方法的内部会调用loadServiceMethod()方法,所以这个将会在下面的动态代理中一并讲解。
      eagerlyValidateMethods(service);
    }

    // 4、创建service类的动态代理类实例
    return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
        new InvocationHandler() {
          private final Platform platform = Platform.get();

          @Override public Object invoke(Object proxy, Method method, @Nullable Object[] args)
              throws Throwable {
            // 5、如果方法是来自对象的方法,则正常调用。像equal()、hashcode()等,在网络请求中这种情况一般不会发生。
            if (method.getDeclaringClass() == Object.class) {
              return method.invoke(this, args);
            }

            // 6、在Android.Platform中isDefaultMethod()方法默认返回false,这里就忽略该方法。
            if (platform.isDefaultMethod(method)) {
              return platform.invokeDefaultMethod(method, service, proxy, args);
            }

            // 7,这是动态代理方法中的核心,也是Retrofi他中的核心代码,这里将创建并最终返回网络请求调用的Call实例
            ServiceMethod<Object, Object> serviceMethod =
                (ServiceMethod<Object, Object>) loadServiceMethod(method);
            OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
            return serviceMethod.adapt(okHttpCall);
          }
        });
  }

这里,我们主要关注动态代理类的生成过程,即使用Proxy.newProxyInstance()创建实例的过程。

**这里通过Proxy.newProxyInstance()对动态代理做个简单介绍:
通过该方法可以为指定接口(可以是多个接口)生成一个代理类的实例,每当调用接口的相关方法时,最终都会调用InvocationHandler类的invoke方法,而invoke方法的返回值就是接口方法的返回值。**

因此,在上面的动态代理invoke()方法中,最终会返回一个调用网络请求的Call对象,该对象就是在网络接口方法中指定的返回值。

获取网络请求Call实例

在上文中提到过,网络请求Call实例是在InvocationHandler的invoke中创建并返回的,也就是上文中的三行核心代码,这里把这三行代码拿出来单独分析。


// 1、获取ServiceMethod实例,
ServiceMethod<Object, Object> serviceMethod =
    (ServiceMethod<Object, Object>) loadServiceMethod(method);

// 2、获取OkhttpCall实例
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
// 3、最终返回调用网络请求的实例
return serviceMethod.adapt(okHttpCall);

创建ServiceMethod

首先,loadServiceMethod()方法会获取一个ServiceMethod对象,这个loadServiceMethod()方法主要是处理网络接口的注解,最终获取http请求相关的所有参数(url、请求头、请求响应解析器等)。

代码如下:

  ServiceMethod<?, ?> loadServiceMethod(Method method) {

    // serviceMethodCache是一个LinkedHashMap,用于缓存ServiceMethod
    // LinkedHashMap内部使用了LRU算法
    ServiceMethod<?, ?> result = serviceMethodCache.get(method);
    if (result != null) return result;

    synchronized (serviceMethodCache) {
      result = serviceMethodCache.get(method);
      if (result == null) {
        // 如果缓存中不存在,那么就根据method创建一个ServiceMethod并放入到缓存中,以便下次使用。
        result = new ServiceMethod.Builder<>(this, method).build();
        serviceMethodCache.put(method, result);
      }
    }
    return result;
  }
ServiceMethod类

在上文loadServiceMethod()方法中最终是通过new ServiceMethod.Builder<>(this, method).build()创建一个ServiceMethod实例的。
这里我们直接看ServiceMethod.Builder的构造方法和build()方法,如下:

Builder(Retrofit retrofit, Method method) {
  this.retrofit = retrofit;
  this.method = method;
  // 1、获取方法的注解
  this.methodAnnotations = method.getAnnotations();
  // 2、获取方法中参数的类型,这是一个Type[]
  this.parameterTypes = method.getGenericParameterTypes();
  // 3、获取方法中每个参数的注解,这是一个二维数组Annotation[][]
  this.parameterAnnotationsArray = method.getParameterAnnotations();
}


public ServiceMethod build() {
  // 1、创建CallAdapter网络适配器,通过工厂方法创建
  callAdapter = createCallAdapter();
  // 2、获取网络响应体类型
  responseType = callAdapter.responseType();
  if (responseType == Response.class || responseType == okhttp3.Response.class) {
    // 这里可以看出响应体需要是ResponseBody
    throw methodError("'"
        + Utils.getRawType(responseType).getName()
        + "' is not a valid response body type. Did you mean ResponseBody?");
  }

  // 3、创建响应解析器,通过工厂方法创建,创建过程和callAdapter方法类似
  responseConverter = createResponseConverter();


  // 4、解析网络接口方法的注解,所有作用于method的注解都在这里解析
  //    例如(GET、POST、HTTP、Multipart、FormUrlEncoded、Headers等)
  for (Annotation annotation : methodAnnotations) {
    parseMethodAnnotation(annotation);
  }

  if (httpMethod == null) {
    // 必须设置Http请求类型
    throw methodError("HTTP method annotation is required (e.g., @GET, @POST, etc.).");
  }

  if (!hasBody) {
    if (isMultipart) {
      throw methodError(
          "Multipart can only be specified on HTTP methods with request body (e.g., @POST).");
    }
    if (isFormEncoded) {
      throw methodError("FormUrlEncoded can only be specified on HTTP methods with "
          + "request body (e.g., @POST).");
    }
  }

  // 5、获取网络接口方法的参数的数量
  int parameterCount = parameterAnnotationsArray.length;
  // 6、创建一个数组,用于存储每个方法参数的注解等信息
  parameterHandlers = new ParameterHandler<?>[parameterCount];
  for (int p = 0; p < parameterCount; p++) {
    // 7、获取第p个参数的类型
    Type parameterType = parameterTypes[p];
    if (Utils.hasUnresolvableType(parameterType)) {
      throw parameterError(p, "Parameter type must not include a type variable or wildcard: %s",
          parameterType);
    }
    // 8、获取第p个该数上所有的注解
    Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
    if (parameterAnnotations == null) {
      throw parameterError(p, "No Retrofit annotation found.");
    }

    // 9、根据参数及参数的注解生成一个ParameterHandler对象
    //    ParameterHandlers类中定义了不同注解的类,用于封装参数。
    //    最终通过ParameterHandler.apply()方法将参数设置到RequestBuilder中
    parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
  }

  if (relativeUrl == null && !gotUrl) {
    throw methodError("Missing either @%s URL or @Url parameter.", httpMethod);
  }
  if (!isFormEncoded && !isMultipart && !hasBody && gotBody) {
    throw methodError("Non-body HTTP method cannot contain @Body.");
  }
  if (isFormEncoded && !gotField) {
    throw methodError("Form-encoded method must contain at least one @Field.");
  }
  if (isMultipart && !gotPart) {
    throw methodError("Multipart method must contain at least one @Part.");
  }

  // 10、创建ServiceMethod对象
  return new ServiceMethod<>(this);
}

这上面代码中对build()方法中的具体功能都做了说明,这里选取几个关键代码深入分析一下。

创建CallAdapter

首先,在build()方法中会通过createCallAdapter()方法获取CallAdapter网络适配器,这个是通过工厂方法生成的,如下:

private CallAdapter<T, R> createCallAdapter() {
  // 1、获取接口方法的返回值类型
  Type returnType = method.getGenericReturnType();
  if (Utils.hasUnresolvableType(returnType)) {
    throw methodError(
        "Method return type must not include a type variable or wildcard: %s", returnType);
  }
  if (returnType == void.class) {
    throw methodError("Service methods cannot return void.");
  }
  // 2、获取该方法中所有的注解
  Annotation[] annotations = method.getAnnotations();
  try {

    // 3、获取CallAdapter对象,这个最终会通过工厂类Factory.get()方法实现,具体实现在子类中如RxJava2CallAdapterFactory
    return (CallAdapter<T, R>) retrofit.callAdapter(returnType, annotations);
  } catch (RuntimeException e) { // Wide exception range because factories are user code.
    throw methodError(e, "Unable to create call adapter for %s", returnType);
  }
}

CallAdapter机制将在下一章节中单独讲解,这里先简单介绍一下。

同样的createResponseConverter()方法创建响应转换器的过程也和createCallAdapter()过程是类似的。

初始化ParameterHandler数组

在build()方法中会获取网络接口参数及对应的注解类型,并将每个参数都根据注解类型封装成不同的ParameterHandler类,最终ParameterHandler数组主要用于RequestBuilder的创建。

该过程比较长,这里就不贴上代码了,可以自行通过build()方法第9个注释处查看具体代码。

创建OkHttpCall

OkHttpCall:就是对Okhttp中的Call做了一层封装,最终在OkHttpCall中会通过Okhttp.Call完成网络请求的操作

完成了ServiceMethod对象的创建后,在InvovationHandler.invoke()方法中就要通过ServiceMethdo对象和网络接口参数,创建一个OkHttpCall对象,这里看下OkHttpCall的构造方法:

  OkHttpCall(ServiceMethod<T, ?> serviceMethod, @Nullable Object[] args) {
    this.serviceMethod = serviceMethod;
    this.args = args;
  }

这个构造方法很简单,就是完成了两个属性的赋值操作。

OkHttpCall是实现网络请求的具体实现类,这个将在下文中具体分析。

在获取到ServiceMethod和OkHttpCall对象后,在Retrofit中将通过ServiceMethod的adapt(OkHttpCall)方法获取网络接口的动态代理对象。

serviceMethod.adapt(okHttpCall);

ServiceMethod.adapt()方法的内部很简单,通过具体的CallAdapter网络适配器获取Call对象,如下:

T adapt(Call<R> call) {
return callAdapter.adapt(call);
}

这样在整个Retrofit.create()方法中就通过动态代理完成了Call对象的获取,这样就可以使用OkHttpCall完成网络请求了。

CallAdapter机制将在下一章节中单独讲解,这里先简单介绍一下。

OkHttpCall实现同步异步请求

在通过网络接口获取了Call对象后,就可以开始完成网络请求了。

这个过程主要是通过Call的具体实现类OkHttpCall实现的,这里对实OkHttpCall的同步请求和异步请求的实现做具体分析。

同步请求方法execute

在获取了网络接口定义的Call对象后,要想实现同步请求只需要调用Call.execute()方法即可,这里根据上一章节中实例演示同步请求代码:

// 5、同步请求获取响应
Response<User> execute = call.execute();
// 
User body = execute.body();

OkHttpCall中的同步方法execute()的逻辑非常请求,主要包括:

  1. 创建一个okhttp3.Call实例
  2. 调动okhttp3.Call的同步方法execute获取响应
  3. 解析响应结果并返回

execute()方法如下:

  @Override 
  public Response<T> execute() throws IOException {
    // 1、定义一个okhttp的Call
    //    看到这里就很清晰了,Retrofit是通过okhttp完成网络请求的
    okhttp3.Call call;

    synchronized (this) {
      if (executed) throw new IllegalStateException("Already executed.");
      executed = true;

      if (creationFailure != null) {
        if (creationFailure instanceof IOException) {
          throw (IOException) creationFailure;
        } else if (creationFailure instanceof RuntimeException) {
          throw (RuntimeException) creationFailure;
        } else {
          throw (Error) creationFailure;
        }
      }

      call = rawCall;
      if (call == null) {
        try {
          // 2、创建okhttp中的call对象
          call = rawCall = createRawCall();
        } catch (IOException | RuntimeException | Error e) {
          throwIfFatal(e); //  Do not assign a fatal error to creationFailure.
          creationFailure = e;
          throw e;
        }
      }
    }

    if (canceled) {
      call.cancel();
    }

    // 3、调用同步方法,并完成响应结果的解析
    return parseResponse(call.execute());
  }
创建okhttp3的Call对象

在上面execute()方法中,okhttp3.Call对象主要是通过createRawCall()方法创建的,这里看下该方法:

  private okhttp3.Call createRawCall() throws IOException {
    okhttp3.Call call = serviceMethod.toCall(args);
    if (call == null) {
      throw new NullPointerException("Call.Factory returned null.");
    }
    return call;
  }

在该方法中,主要通过serviceMethod.toCall()方法完成okhttp3.Call对象的创建。

接下来,我们看下toCall()方法:

okhttp3.Call toCall(@Nullable Object... args) throws IOException {
    // 1、创建RequestBuilder对象,在该对象中将包装网络请求相关的参数
    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;

    int argumentCount = args != null ? args.length : 0;
    if (argumentCount != handlers.length) {
      throw new IllegalArgumentException("Argument count (" + argumentCount
          + ") doesn't match expected count (" + handlers.length + ")");
    }

    // 2、网络请求接口参数封装到RequestBuilder对象中,这样可以获取整个网络请求完整的参数
    for (int p = 0; p < argumentCount; p++) {
      handlers[p].apply(requestBuilder, args[p]);
    }

    // 3、通过RequestBuilder.build()方法创建okhttp3所需要的Request对象
    // 4、最终通过CallFactory.newCall()创建okhttp3网络请求的Call对象(这个CallFactory对象就是在Retrofit创建时创建的OkHttpClient对象)
    return callFactory.newCall(requestBuilder.build());
}

toCall方法的功能逻辑也很清晰:

  1. 封装所有网络请求参数到RequestBuilder
  2. RequestBuilder.build()方法将所有参数都解析成Okhttp3的网络参数的格式。并最终生成一个okhttp3.Request对象。
  3. 通过CallFactory也就是OkHttpClient对象创建一个Call实例。

这里需要注意的就是Retrofit中的RequestBuilder类,该类中实现了Retrofit到okhttp3的转换。

解析okhttp请求结果

当Retrofit通过okhttp3完成了同步请求后,在获取请求结果后,将会对该结果进行解析,最终将okhttp的结果转化成Retrofit的请求结果。

这里我们看下OkHttpCall.parseResponse()方法:

  Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
    // 1、获取okhttp中的响应体
    ResponseBody rawBody = rawResponse.body();

    // 这里会移除响应体,在处理一些错误时会使用Retrofit中定义的响应体,例如Response.error()方法
    rawResponse = rawResponse.newBuilder()
        .body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength()))
        .build();

    // 2、获取响应码
    int code = rawResponse.code();

    // 异常结果处理 start
    if (code < 200 || code >= 300) {
      try {
        // 返回错误响应
        ResponseBody bufferedBody = Utils.buffer(rawBody);
        return Response.error(bufferedBody, rawResponse);
      } finally {
        rawBody.close();
      }
    }

    if (code == 204 || code == 205) {
      rawBody.close();
      return Response.success(null, rawResponse);
    }
    // 异常结果处理 end


    // 3、对响应结果进行处理
    ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);
    try {
      // 4、通过响应解析器将结果转化成对应的响应结果类
      T body = serviceMethod.toResponse(catchingBody);
      // 5、获取具体Response类(body:网络请求接口中定义的结果类;rawResponse:okhttp3中解析的响应体)
      return Response.success(body, rawResponse);
    } catch (RuntimeException e) {
      // If the underlying source threw an exception, propagate that rather than indicating it was
      // a runtime exception.
      catchingBody.throwIfCaught();
      throw e;
    }
  }

在parseResponse()方法中,主要通过serviceMethod.toResponse()方法将okhttp的响应体内容解析成网络接口中指定的类型,在这个方法中主要使用了响应解析器,如下:

  R toResponse(ResponseBody body) throws IOException {
    return responseConverter.convert(body);
  }

最后通过Response.success(body, rawResponse)方法创建一个Response对象,该对象中封装了通过okhttp3获取的网络请求。

  public static <T> Response<T> success(@Nullable T body, okhttp3.Response rawResponse) {
    checkNotNull(rawResponse, "rawResponse == null");
    if (!rawResponse.isSuccessful()) {
      throw new IllegalArgumentException("rawResponse must be successful response");
    }
    return new Response<>(rawResponse, body, null);
  }

这样整个同步请求就完成了。

异步请求方法enqueue

通过Call对象实现异步请求,只需要调用OkHttpCall.enqueue()方法即可:

// 实现异步网络请求
call.enqueue(new Callback<User>() {
    @Override
    public void onResponse(Call<User> call, Response<User> response) {
        // 获取用户信息
        User body = response.body();
    }

    @Override
    public void onFailure(Call<User> call, Throwable t) {

    }
});

异步网络请求enqueue()方法内部的逻辑也非常清晰,基本和上文中同步请求的步骤一致,主要包括:

  1. 创建一个okhttp3.Call实例
  2. 调动okhttp3.Call的同步方法enqueue获取响应
  3. 解析响应结果
  4. 最终调用回调接口传递网络请求结果
  @Override 
  public void enqueue(final Callback<T> callback) {
    checkNotNull(callback, "callback == null");

    okhttp3.Call call;
    Throwable failure;

    synchronized (this) {
      if (executed) throw new IllegalStateException("Already executed.");
      executed = true;

      call = rawCall;
      failure = creationFailure;
      if (call == null && failure == null) {
        try {
          // 1、创建okhttp3.Call对象
          call = rawCall = createRawCall();
        } catch (Throwable t) {
          throwIfFatal(t);
          failure = creationFailure = t;
        }
      }
    }

    if (failure != null) {
      callback.onFailure(this, failure);
      return;
    }

    if (canceled) {
      call.cancel();
    }
    // 2、调用okhttp3.Call的异步方法enqueue()
    call.enqueue(new okhttp3.Callback() {
      @Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {
        Response<T> response;
        try {
          // 3、解析网络响应
          response = parseResponse(rawResponse);
        } catch (Throwable e) {
          callFailure(e);
          return;
        }

        try {
          // 4、调用回调方法
          callback.onResponse(OkHttpCall.this, response);
        } catch (Throwable t) {
          t.printStackTrace();
        }
      }

      @Override public void onFailure(okhttp3.Call call, IOException e) {
        callFailure(e);
      }

      private void callFailure(Throwable e) {
        try {
          callback.onFailure(OkHttpCall.this, e);
        } catch (Throwable t) {
          t.printStackTrace();
        }
      }
    });
  }

异步方法的主要逻辑基本在同步方法中讲过了,这里就不在介绍了。

总结

这样,整个Retrofit完成网络请求的流程的源码就都分析完了。

在该源码分析中,CallAdapter获取具体网络适配器的实现原理将会在下一章节中具体讲解。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值