美文网首页
Retrofit源码学习之一

Retrofit源码学习之一

作者: leilifengxingmw | 来源:发表于2018-09-08 14:20 被阅读10次

先从简单的使用开始

implementation 'com.squareup.retrofit2:retrofit:2.4.0'

Retrofit 使用方法注解的方式把Java接口转化成HTTP请求

public interface GitHubService {
 //获取github上用户所有的仓库
  @GET("users/{user}/repos")
  Call<List<Repo>> listRepos(@Path("user") String user);
}

Retrofit使用四部曲

//1. 构建一个Retrofit实例
  Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("https://api.github.com/")
                .build();
        //2. 生成一个GitHubService接口的实现
        GitHubService service = retrofit.create(GitHubService.class);
        //3. 创建一个请求
        Call<List<Repo>> listCall = service.listRepos("octocat");
        try {
            //4. 同步执行
            Response<List<Repo>> response = listCall.execute();
        } catch (IOException e) {
            e.printStackTrace();
        }
        //4. 异步执行
        listCall.enqueue(new Callback<List<Repo>>() {
            @Override
            public void onResponse(Call<List<Repo>> call, Response<List<Repo>> response) {

            }

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

            }
        });

1.构建一个Retrofit实例。

首先看一下Retrofit.Builder类的构造函数

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

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

Retrofit.Builder类的构造函数内部初始化了一个Platform实例。Platform代表Retrofit的使用平台。我们在Android中使用Retrofit,平台就是Android。

static class Android extends Platform {
    //默认的回调执行器
    @Override public Executor defaultCallbackExecutor() {
      return new MainThreadExecutor();
    }

    @Override CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor
 callbackExecutor) {
      if (callbackExecutor == null) throw new AssertionError();
      return new ExecutorCallAdapterFactory(callbackExecutor);
    }

    static class MainThreadExecutor implements Executor {
    //隐隐约约看到了熟悉的Handler。可以猜想,回调之所以是在主线程执行,还是使用handler来实现的  
      private final Handler handler = new Handler(Looper.getMainLooper());

      @Override public void execute(Runnable r) {
        handler.post(r);
      }
    }
  }

接下来看一下Retrofit.Builder类的build()方法

public Retrofit build() {
      if (baseUrl == null) {
        throw new IllegalStateException("Base URL required.");
      }
      //初始化callFactory 
      okhttp3.Call.Factory callFactory = this.callFactory;
      if (callFactory == null) {
        callFactory = new OkHttpClient();
      }
      //初始化回调执行器
      Executor callbackExecutor = this.callbackExecutor;
      if (callbackExecutor == null) {
        callbackExecutor = platform.defaultCallbackExecutor();
      }

      // 防御性拷贝callAdapterFactories,并添加默认的Call adapter
      List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>
                                               (this.callAdapterFactories);
      //添加默认的Call adapter
      callAdapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));

      // 防御性拷贝converters,并添加内置的converter factory 
      List<Converter.Factory> converterFactories =
          new ArrayList<>(1 + this.converterFactories.size());
      //首先添加内置的converter factory到converter factory list中
      converterFactories.add(new BuiltInConverters());
      converterFactories.addAll(this.converterFactories);

      return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
          unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
    }

Retrofit.Builder类的build()方法初始化了三个重要的成员,先记一下。

  • okhttp3.Call.Factory callFactory:
  • List<CallAdapter.Factory> callAdapterFactories
  • List<Converter.Factory> converterFactories

最后Retrofit.Builder类的build()方法返回了一个Retrofit实例。

2. 生成一个GitHubService接口的实现

GitHubService service = retrofit.create(GitHubService.class);
public <T> T create(final Class<T> service) {
    //1. 首先验证service是否合法
    Utils.validateServiceInterface(service);
    //2. 是否提前创建service里面的所有方法
    if (validateEagerly) {
      eagerlyValidateMethods(service);
    }
    //3. 创建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 {
             // service的所有方法调用,最终会转发到这里
            // 如果是Object的方法,就正常调用
            if (method.getDeclaringClass() == Object.class) {
              return method.invoke(this, args);
            }
            //如果是default方法(Java8中的默认方法),Android中不用管,一定是false
            if (platform.isDefaultMethod(method)) {
              return platform.invokeDefaultMethod(method, service, proxy, args);
            }
            //3.1
            ServiceMethod<Object, Object> serviceMethod =(ServiceMethod<Object, Object>) 
loadServiceMethod(method);
            //3.2
            OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
            //3.3
            return serviceMethod.callAdapter.adapt(okHttpCall);
          }
        });
  }

create()方法内部创建了我们传入的service的动态代理。就是说我们我们调用service中的任何方法,都会转发到这个动态代理的invoke()方法中。

3. 创建一个请求

Call<List<Repo>> listCall = service.listRepos("octocat");

这时,方法就转发到service动态代理的invoke()方法中了。

//3.1
ServiceMethod<Object, Object> serviceMethod =(ServiceMethod<Object, Object>) 
loadServiceMethod(method);
//3.2
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
//3.3
 return serviceMethod.callAdapter.adapt(okHttpCall);
3.1构建一个ServiceMethod实例,ServiceMethod把对接口方法的调用转为一个HTTP调用
ServiceMethod<Object, Object> serviceMethod =(ServiceMethod<Object, Object>) 
loadServiceMethod(method);

加载method对应的ServiceMethod。如果缓存中存在就直接返回,否则创建一个ServiceMethod加入缓存,然后返回。可见每个ServiceMethod只会创建一次。

//缓存ServiceMethod实例
private final Map<Method, ServiceMethod<?, ?>> serviceMethodCache = new
 ConcurrentHashMap<>();
ServiceMethod<?, ?> loadServiceMethod(Method method) {
    ServiceMethod<?, ?> result = serviceMethodCache.get(method);
    if (result != null) return result;

    synchronized (serviceMethodCache) {
      result = serviceMethodCache.get(method);
      if (result == null) {
        result = new ServiceMethod.Builder<>(this, method).build();
        serviceMethodCache.put(method, result);
      }
    }
    return result;
  }

接下来看一下ServiceMethod.Builder这个类。ServiceMethod.Builder负责检查我们在接口中定义的方法上的注解,来构造一个可重复使用的服务方法。这个过程需要用到代价非常昂贵的反射操作,所以最好是只构建一个方法一次,然后重复使用它。Builder的实例不能被重用。

ServiceMethod.Builder的构造函数

Builder(Retrofit retrofit, Method method) {
      this.retrofit = retrofit;
      this.method = method;
      this.methodAnnotations = method.getAnnotations();
      this.parameterTypes = method.getGenericParameterTypes();
      this.parameterAnnotationsArray = method.getParameterAnnotations();
    }

ServiceMethod.Builder的build方法简化版

public ServiceMethod build() {
      //1. 创建callAdapter
      callAdapter = createCallAdapter();
      responseType = callAdapter.responseType();
      ...
     //2. 创建responseConverter
      responseConverter = createResponseConverter();
     //3. 处理方法注解
      for (Annotation annotation : methodAnnotations) {
        parseMethodAnnotation(annotation);
      }
      ...
      int parameterCount = parameterAnnotationsArray.length;
      //4. 创建parameterHandlers
      parameterHandlers = new ParameterHandler<?>[parameterCount];
      for (int p = 0; p < parameterCount; p++) {
        Type parameterType = parameterTypes[p];
        Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
        parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
      }
      ...
      //5. 返回一个ServiceMethod实例
      return new ServiceMethod<>(this);
    }

  1. 创建callAdapter:把一个类型参数为R的retrofit2.Call转化成T类型的对象(Call<R>转化成T)。CallAdapter的实例由构建Retrofit时候通过{Retrofit.Builder#addCallAdapterFactory(Factory)}方法设置。

createCallAdapter()方法简化版

private CallAdapter<T, R> createCallAdapter() {
      Type returnType = method.getGenericReturnType();
      ...
      Annotation[] annotations = method.getAnnotations();
      try {
        //返回CallAdapter
        return (CallAdapter<T, R>) retrofit.callAdapter(returnType, annotations);
      } catch (RuntimeException e) {
        throw methodError(e, "Unable to create call adapter for %s", returnType);
      }
    }

可见CallAdapter还是由Retrofit提供的。

Retrofit的callAdapter()方法

public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {
    return nextCallAdapter(null, returnType, annotations);
  }

Retrofit的nextCallAdapter()方法简化版

 public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, 
Type returnType,
      Annotation[] annotations) {
    checkNotNull(returnType, "returnType == null");
    checkNotNull(annotations, "annotations == null");

    int start = callAdapterFactories.indexOf(skipPast) + 1;
    //遍历callAdapterFactories,返回合适的CallAdapter
    for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
      CallAdapter<?, ?> adapter = callAdapterFactories.get(i).get(returnType,
 annotations, this);
      if (adapter != null) {
        return adapter;
      }
    }

Retrofit的callAdapter()方法内部会去遍历callAdapterFactories这个list,根据返回类型和注解,返回合适的callAdapter。
当我们构建一个默认的Retrofit实例的时候,在Retrofit.Builder的build()方法内部回传入一个平台相关的CallAdapter.Factory

public Retrofit build() {
      Executor callbackExecutor = this.callbackExecutor;
      if (callbackExecutor == null) {
        callbackExecutor = platform.defaultCallbackExecutor();
      }

      // Make a defensive copy of the adapters and add the default Call adapter.
      List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>
(this.callAdapterFactories);
      //添加平台相关的CallAdapter.Factory
      callAdapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
    }

而Android平台相关的默认的CallAdapter.Factory就是ExecutorCallAdapterFactory。ExecutorCallAdapterFactory这个类暂且不去管他。现在算是找到ServiceMethod 的callAdapter了。

  1. 创建Converter<ResponseBody, T> responseConverter。负责把okhttp3.ResponseBody转化为T类型的对象。
private Converter<ResponseBody, T> createResponseConverter() {
      Annotation[] annotations = method.getAnnotations();
      try {
        //从retrofit中获取
        return retrofit.responseBodyConverter(responseType, annotations);
      } catch (RuntimeException e) { // Wide exception range because factories are user code.
        throw methodError(e, "Unable to create converter for %s", responseType);
      }
    }

可见responseConverter还是由Retrofit提供的。

public <T> Converter<ResponseBody, T> responseBodyConverter(Type type, 
Annotation[] annotations) {
    return nextResponseBodyConverter(null, type, annotations);
  }
public <T> Converter<ResponseBody, T> nextResponseBodyConverter(
      @Nullable Converter.Factory skipPast, Type type, Annotation[] annotations) {
    checkNotNull(type, "type == null");
    checkNotNull(annotations, "annotations == null");

    int start = converterFactories.indexOf(skipPast) + 1;
    //遍历converterFactories,找到合适的converter
    for (int i = start, count = converterFactories.size(); i < count; i++) {
      Converter<ResponseBody, ?> converter =
          converterFactories.get(i).responseBodyConverter(type, annotations, this);
      if (converter != null) {
        //noinspection unchecked
        return (Converter<ResponseBody, T>) converter;
      }
    }
  }

Retrofit的responseBodyConverter()方法内部会去遍历converterFactories这个list,根据返回类型和注解,返回合适的responseConverter。
当我们构建一个默认的Retrofit实例的时候,在Retrofit.Builder的build()方法内部回传入一个内置的BuiltInConverters

public Retrofit build() {
      ...
      // Make a defensive copy of the converters.
      List<Converter.Factory> converterFactories =
          new ArrayList<>(1 + this.converterFactories.size());

      // 首先添加一个内置的converter factory 
      converterFactories.add(new BuiltInConverters());
      converterFactories.addAll(this.converterFactories);

      return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
          unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
    }

BuiltInConverters这个类暂且不去管它。现在为ServiceMethod找到了responseConverter。

  1. parseMethodAnnotation:负责解析检查方法注解,暂且略过。

  2. 创建parameterHandlers,负责解析 API 定义时每个方法的参数,并在构造 HTTP 请求时设置参数;这个过程暂且不去看。

每个参数都会有一个 ParameterHandler,由 ServiceMethod#parseParameter 方法负责创建,其主要内容就是解析每个参数使用的注解类型(诸如 Path,Query,Field 等),对每种类型进行单独的处理。API 方法中除了 @Body 和 @Part 类型的参数,都利用 Converter.Factory.stringConverter 进行转换,而 @Body 和 @Part 类型的参数则利用 Converter.Factory.requestBodyConverter 进行转换。

现在ServiceMethod.Builder的build()方法可以返回一个实例了。

public ServiceMethod build() {
      //5. 返回一个ServiceMethod实例
      return new ServiceMethod<>(this);
    }

3.2现在是创建一个OkHttpCall实例
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
3.3 返回结果
return serviceMethod.callAdapter.adapt(okHttpCall);
 T adapt(Call<R> call) {
    return callAdapter.adapt(call);
  }

我们构建Retrofit实例的时候,默认会为我们添加一个平台相关的defaultCallAdapterFactory。

@Override CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
      if (callbackExecutor == null) throw new AssertionError();
      //Android平台传入的是MainThreadExecutor
      return new ExecutorCallAdapterFactory(callbackExecutor);
    }

final class ExecutorCallAdapterFactory extends CallAdapter.Factory {
  //回调执行器
  final Executor callbackExecutor;

  ExecutorCallAdapterFactory(Executor callbackExecutor) {
    this.callbackExecutor = callbackExecutor;
  }

  @Override
  public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
    if (getRawType(returnType) != Call.class) {
      return null;
    }
    final Type responseType = Utils.getCallResponseType(returnType);
    return new CallAdapter<Object, Call<?>>() {
      @Override public Type responseType() {
        return responseType;
      }

      @Override public Call<Object> adapt(Call<Object> call) {
        return new ExecutorCallbackCall<>(callbackExecutor, call);
      }
    };
  }
  //实现了retrofit2.Call接口
  static final class ExecutorCallbackCall<T> implements Call<T> {
    final Executor callbackExecutor;
    final Call<T> delegate;

    ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
      this.callbackExecutor = callbackExecutor;
      this.delegate = delegate;
    }

    @Override public void enqueue(final Callback<T> callback) {
      checkNotNull(callback, "callback == null");
      //调用代理的enqueue方法,并在执行完毕后使用回调执行器切换线程
      delegate.enqueue(new Callback<T>() {
        @Override public void onResponse(Call<T> call, final Response<T> response) {
          //执行成功,使用回调执行器切换线程
          callbackExecutor.execute(new Runnable() {
            @Override public void run() {
              if (delegate.isCanceled()) {
                // Emulate OkHttp's behavior of throwing/delivering an IOException on cancellation.
                callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled"));
              } else {
                callback.onResponse(ExecutorCallbackCall.this, response);
              }
            }
          });
        }

        @Override public void onFailure(Call<T> call, final Throwable t) {
          //执行失败,切换线程
          callbackExecutor.execute(new Runnable() {
            @Override public void run() {
              callback.onFailure(ExecutorCallbackCall.this, t);
            }
          });
        }
      });
    }

    @Override public boolean isExecuted() {
      return delegate.isExecuted();
    }
    //调用代理对象的execute()方法
    @Override public Response<T> execute() throws IOException {
      return delegate.execute();
    }

    @Override public void cancel() {
      delegate.cancel();
    }

    @Override public boolean isCanceled() {
      return delegate.isCanceled();
    }

    @SuppressWarnings("CloneDoesntCallSuperClone") // Performing deep clone.
    @Override public Call<T> clone() {
      return new ExecutorCallbackCall<>(callbackExecutor, delegate.clone());
    }

    @Override public Request request() {
      return delegate.request();
    }
  }
}

我们调用默认的CallAdapterFactory的get()方法,创建了一个CallAdapter的匿名内部类。

  @Override
  public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
    if (getRawType(returnType) != Call.class) {
      return null;
    }
    final Type responseType = Utils.getCallResponseType(returnType);
    //返回一个CallAdapter实例。
    return new CallAdapter<Object, Call<?>>() {
      @Override public Type responseType() {
        return responseType;
      }

      @Override public Call<Object> adapt(Call<Object> call) {
        //返回ExecutorCallbackCall实例
        return new ExecutorCallbackCall<>(callbackExecutor, call);
      }
    };
  }

CallAdapter的adapt()方法返回了一个ExecutorCallbackCall实例。ExecutorCallbackCall内部的execute()和enqueue()方法,就是调用被代理对象的方法。如果是调用被代理对象的enqueue()方法,并在执行完毕后使用回调执行器切换线程。这里的被代理对象就是我们传入的OkHttpCall的实例。再贴一下代码。

ServiceMethod<Object, Object> serviceMethod =(ServiceMethod<Object, Object>) 
loadServiceMethod(method);

OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);

return serviceMethod.callAdapter.adapt(okHttpCall);

4. 现在到了Retrofit使用四部曲的第四步,执行请求。

4.1 同步请求execute(),ExecutorCallbackCall内部的execute()就是调用了代理对象的execute()方法。

@Override public Response<T> execute() throws IOException {
      return delegate.execute();
    }

OkHttpCall的execute方法。

@Override public Response<T> execute() throws IOException {
    okhttp3.Call call;

    synchronized (this) {
      //1. 一个请求只能被执行一次
      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. 创建一个okhttp3.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. 转换okhttp3.Call的执行返回的响应
    return parseResponse(call.execute());
  }
  1. 一个请求只能被执行一次。
  2. createRawCall()方法,创建一个okhttp3.Call
private okhttp3.Call createRawCall() throws IOException {
    okhttp3.Call call = serviceMethod.toCall(args);
    if (call == null) {
      throw new NullPointerException("Call.Factory returned null.");
    }
    return call;
  }

createRawCall()方法返回的是一个okhttp3.RealCall的实例。

  1. 转换okhttp3.Call的执行返回的响应
 Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
    //1. 单独把响应体取出来
    ResponseBody rawBody = rawResponse.body();

    //移除rawResponse的本来的响应体,传入一个没有内容的响应体
    rawResponse = rawResponse.newBuilder()
        .body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength()))
        .build();

    int code = rawResponse.code();
    if (code < 200 || code >= 300) {
      try {
        //缓存整个原始响应体,避免将来可能出现的I/O异常
        ResponseBody bufferedBody = Utils.buffer(rawBody);
        //构建一个错误的响应返回,并把bufferedBody作为错误的响应体
        return Response.error(bufferedBody, rawResponse);
      } finally {
        rawBody.close();
      }
    }

    if (code == 204 || code == 205) {
      rawBody.close();
      //构建一个正确的响应返回,但是响应体为null
      return Response.success(null, rawResponse);
    }

    ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);
    try {
      //把原始响应体转化成我们希望的数据类型
      T body = serviceMethod.toResponse(catchingBody);
      //构建一个成功的响应体返回,并把转化后的数据作为响应体。
      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首先会对响应做一些预处理,如果没有什么异常的话,就构建一个成功的响应返回。返回的响应的响应体就是我们希望的数据类型。

4.2 异步请求execute(),ExecutorCallbackCall内部的execute()就是调用了代理对象的execute()方法。

OkHttpCall的enqueue()方法

  @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) {
          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)
          throws IOException {
        Response<T> response;
        try {
          //把okhttp3.Response转换成retrofit2的Response  
          response = parseResponse(rawResponse);
        } catch (Throwable e) {
          callFailure(e);
          return;
        }
        //3. 成功的回调
        callSuccess(response);
      }

      @Override public void onFailure(okhttp3.Call call, IOException e) {
        try {
          //4. 失败的回调  
          callback.onFailure(OkHttpCall.this, e);
        } catch (Throwable t) {
          t.printStackTrace();
        }
      }

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

      private void callSuccess(Response<T> response) {
        try {
          callback.onResponse(OkHttpCall.this, response);
        } catch (Throwable t) {
          t.printStackTrace();
        }
      }
    });
  }

OkHttpCall的enqueue()方法和execute()方法一样,先判断请求是否执行过了。如果没有执行,就构建一个okhttp3.Call的实例。和execute()方法不同的是,这里使用了okhttp3.Call的enqueue()方法。

至此:Retrofit使用四部曲就分析完了。

参考链接

  1. Retrofit
  2. Android Retrofit 2.0使用
  3. github
  4. 拆轮子系列:拆 Retrofit

相关文章

网友评论

      本文标题:Retrofit源码学习之一

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