Retrofit 原理源码分析

Retrofit 依赖

// 添加依赖
implementation 'com.squareup.retrofit2:retrofit:2.6.0'
implementation 'com.google.code.gson:gson:2.8.5'
implementation 'com.squareup.retrofit2:converter-gson:2.6.0'

Retrofit 的简单使用

Retrofit 官方示例文档

本篇博客直接使用官方的示例,来获取 octocat 账户下第一个仓库的名称。

// 定义一个接口
public interface GitHubService {
  @GET("users/{user}/repos")
  Call> listRepos(@Path("user") String user);
}

// 实例化过程和请求网络数据
Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("https://api.github.com")
        .addConverterFactory(GsonConverterFactory.create())
        .build();

GitHubService gitHubApi = retrofit.create(GitHubService.class);
Call> call = gitHubApi.listRepos("octocat");

call.enqueue(new Callback>() {
    @Override
    public void onResponse(Call> call, Response> response) {
        mContentTextView.setText(response.body().get(0).getName() + " ");
    }

    @Override
    public void onFailure(Call> call, Throwable t) {
        Log.e(TAG, "onFailure: " + t.toString());
    }
});

Retrofit 源码解析

源码查看原则,最近原则和只看我们关心的,那么就从 call.enqueue()看起,发现是一个接口定义的方法,暂时放弃,往上看 GitHubService gitHubApi = retrofit.create(GitHubService.class); retrofit 是怎么将一个接口转化为实现类的。

public interface Call extends Cloneable {
  // ******
  void enqueue(Callback callback);
}
// Retrofit#create()
public  T create(final Class service) {
  // 校验:API 方法的声明必须声明在接口里边,并且该接口不能有父接口
  Utils.validateServiceInterface(service);
  if (validateEagerly) { //激进的验证方式,一般不这么用 
    eagerlyValidateMethods(service); 
  }
  return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class[] { service },
      new InvocationHandler() {
        private final Platform platform = Platform.get();
        private final Object[] emptyArgs = new Object[0];

        @Override public @Nullable Object invoke(Object proxy, Method method,
            @Nullable Object[] args) throws Throwable {
          // If the method is a method from Object then defer to normal invocation.
          if (method.getDeclaringClass() == Object.class) {
            return method.invoke(this, args);
          }
          if (platform.isDefaultMethod(method)) {
            return platform.invokeDefaultMethod(method, service, proxy, args);
          }
          return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
        }
      });
}

这是一个动态代理,这里代理的是 GitHubService中定义的 API方法,其中 invoke()方法也是抽象类 ServiceMethod 中的抽象方法,等下贴出,那我们只能查看 invoke 调用处 loadServiceMethod(method)

ServiceMethod loadServiceMethod(Method method) {
  ServiceMethod result = serviceMethodCache.get(method);
  if (result != null) return result;

  synchronized (serviceMethodCache) {
    result = serviceMethodCache.get(method);
    if (result == null) {
      result = ServiceMethod.parseAnnotations(this, method);
      serviceMethodCache.put(method, result);
    }
  }
  return result;
}

这里用到了缓存,默认缓存中是没有的,解析注解之后重新放到了缓存中,重点是怎么解析注解的,来一块看看;是一个单独的抽象类,invoke() 抽象方法也在其中。

abstract class ServiceMethod {
  static  ServiceMethod parseAnnotations(Retrofit retrofit, Method method) {
    
    // 这个 RequestFactory 里边存放的是:1.我们在 API 接口里边定义的方法的全部信息,包括方法的返回值,
    // 方法的参数和方法的注解信息; 2.通过 Builder 模式构造Retrofit实例时,组装的参数,如 baseUrl 信息等
    RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);

    // ******
    // HttpServiceMethod.parseAnnotations()调用的是一个静态方法,该方法返回值是 ServiceMethod,
    // 由下一步的查看源码可以知道,HttpServiceMethod 是 ServiceMethod 的实现类
    return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
  }

  abstract @Nullable T invoke(Object[] args);
}
// RequestFactory 解析在接口中定义的方法
// RequestFactory#parseAnnotations(retrofit, method)
static RequestFactory parseAnnotations(Retrofit retrofit, Method method) {
  return new Builder(retrofit, method).build();
}

RequestFactory build() {
  for (Annotation annotation : methodAnnotations) {
     // 该例子中解析的是 GithubService 接口中每个方法的信息
     // 解析内容包括: 请求方法 httpMethod,请求相对path,Headers注解,是否标记Multipart 和 FormUrlEncoded注解等等
    parseMethodAnnotation(annotation);  
  }
  // ...省略一些校验...
  return new RequestFactory(this);
}

// RequestFactory里边大概组装的信息有这些,不在啰嗦解析过程了
RequestFactory(Builder builder) {
  method = builder.method;
  baseUrl = builder.retrofit.baseUrl;
  httpMethod = builder.httpMethod;
  relativeUrl = builder.relativeUrl;
  headers = builder.headers;
  contentType = builder.contentType;
  hasBody = builder.hasBody;
  isFormEncoded = builder.isFormEncoded;
  isMultipart = builder.isMultipart;
  parameterHandlers = builder.parameterHandlers;
  isKotlinSuspendFunction = builder.isKotlinSuspendFunction;
}

到这里我们捋一捋流程,我们查看动态代理里边的 invoke()方法,发现是抽象泛型类 ServiceMethod的一个抽象方法;然后我们查看了 invoke() 被调用的地方,通过跟进,最终调用方是HttpServiceMethodHttpServiceMethodServiceMethod.parseAnnotations()方法的返回值,到这里明白了动态代理里边的 invoke() 实际上走的是 HttpServiceMethod 类的 invoke() 方法。

/** Adapts an invocation of an interface method into an HTTP call. */
abstract class HttpServiceMethod extends ServiceMethod {
    // ....
  @Override final @Nullable ReturnT invoke(Object[] args) {
  Call call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
    return adapt(call, args);
    }

    protected abstract @Nullable ReturnT adapt(Call call, Object[] args);
    // ***
}

// 这里通过 requestFactory,args,callFactory,和 responseConverter 几个参数,创建了一个新的 OkHttpCall,
// 至于上边几个参数什么意思,等下就会分析到
// 最终 invoke() 调用抽象方法 adapt(),其中 call 就是创建的 OkHttpCall,我们只要找到 adapt() 的实现的地方即可,这里暂且放下

有一行代码还没看 return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);来分析一下:

// HttpServiceMethod#ParseAnnotations()  经过精简后的代码
static  HttpServiceMethod parseAnnotations(
    Retrofit retrofit, Method method, RequestFactory requestFactory) {
  boolean isKotlinSuspendFunction = requestFactory.isKotlinSuspendFunction;
  Annotation[] annotations = method.getAnnotations();
  Type adapterType;
  if (isKotlinSuspendFunction) {
    // ******
  } else {
    adapterType = method.getGenericReturnType();
  }

  CallAdapter callAdapter =
      createCallAdapter(retrofit, method, adapterType, annotations);
  Type responseType = callAdapter.responseType();
  // ******

  Converter responseConverter =
      createResponseConverter(retrofit, method, responseType);

  okhttp3.Call.Factory callFactory = retrofit.callFactory;
  // ******
  // 注意这个返回值CallAdapted,是 HttpServiceMethod 的一个实现类,其实是 HttpServiceMethod 的一个静态内部类,
  // 那么经过上面的分析,自然最终是调用到了 CallAdapted类的 adapt()方法里边去了
  return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
}
abstract class HttpServiceMethod extends ServiceMethod {
    // ******
  static final class CallAdapted extends HttpServiceMethod {
    private final CallAdapter callAdapter;

    CallAdapted(RequestFactory requestFactory, okhttp3.Call.Factory callFactory,
      Converter responseConverter,
      CallAdapter callAdapter) {
       super(requestFactory, callFactory, responseConverter);
       this.callAdapter = callAdapter;
     }

    @Override protected ReturnT adapt(Call call, Object[] args) {
      return callAdapter.adapt(call);  // 最终调用了 CallAdapter.adapt()方法,回过头来分析 callAdapter 是什么
     }
    }
}

CallAdapted 实例化时参数分析

也即是 return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);中的各个参数,是什么?怎么来的?

  • requestFactory 是什么
  • callFactory 是什么
  • responseConverter 是什么
  • callAdapter 是什么

其中我们已经分析过 requestFactory了,就是 API接口中定义的方法的解析类,做了一层封装;看下 callFactory 是什么?是在 Retrofit.java类中做的声明 okhttp3.Call.Factory callFactory,其实就是 OkHttpClient 。

// callFactory 是在 Retrofit$Builder.build() 静态内部类 Builder 的一个 build()方法里边赋值操作的,callFactory其实就是OkhttpClient
public Retrofit build() {
  okhttp3.Call.Factory callFactory = this.callFactory;
  if (callFactory == null) {
    callFactory = new OkHttpClient();
  }

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

  // Make a defensive copy of the adapters and add the default Call adapter.
  List callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
  callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));

  // Make a defensive copy of the converters.
  List converterFactories = new ArrayList<>(
      1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize());

  // Add the built-in converter factory first. This prevents overriding its behavior but also
  // ensures correct behavior when using converters that consume all types.
  converterFactories.add(new BuiltInConverters());
  converterFactories.addAll(this.converterFactories);
  converterFactories.addAll(platform.defaultConverterFactories());

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

responseConverter是什么呢?经过追踪是从 converterFactories 集合里边取得,而这个集合的赋值操作也在上面这个 build() 方法里边,是一些内置的转换工厂,还有一个是我们在实例化 Retrofit 时添加的自己的 ConverterFactory。

// Retrofit#nextResponseBodyConverter()
public  Converter nextResponseBodyConverter(
    @Nullable Converter.Factory skipPast, Type type, Annotation[] annotations) {
 
  int start = converterFactories.indexOf(skipPast) + 1;
  for (int i = start, count = converterFactories.size(); i < count; i++) {
    Converter converter =
        converterFactories.get(i).responseBodyConverter(type, annotations, this);
    if (converter != null) {
      //noinspection unchecked
      return (Converter) converter;
    }
  }
    // ******
}
Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("https://api.github.com")
        .addConverterFactory(GsonConverterFactory.create()) //将响应数据,转化为对应的bean的转化工厂
        .build();

现在就剩下 callAdapter不知道是什么了,我们重点分析一下


Type adapterType = method.getGenericReturnType();
CallAdapter callAdapter =
        createCallAdapter(retrofit, method, adapterType, annotations);



// Retrofit#nextCallAdapter
public CallAdapter nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType,Annotation[] annotations) {

  int start = callAdapterFactories.indexOf(skipPast) + 1;
  for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
    CallAdapter adapter = callAdapterFactories.get(i).get(returnType, annotations, this);
    if (adapter != null) {
      return adapter;
    }
  }

    // ******
}

callAdapter 从集合 callAdapterFactories中存储的CallAdapter.Factory中取出来的,该集合也是在 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 callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));

Platform 该类是与平台相关的,内部有两个实现类 Java8Android,先看下 callbackExecutor 在 Android 里边的实现为:

// Platform$Android
@Override public Executor defaultCallbackExecutor() {
  return new MainThreadExecutor();
}

// Platform$Android$MainThreadExecutor
static class MainThreadExecutor implements Executor {
  private final Handler handler = new Handler(Looper.getMainLooper());

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

callbackExecutor 是一个线程的管理类,工作在主线程。

platform.defaultCallAdapterFactories(callbackExecutor) 的实现主要在 DefaultCallAdapterFactory.java 类的 get() 方法里边。

final class DefaultCallAdapterFactory extends CallAdapter.Factory {
  private final @Nullable Executor callbackExecutor;

  DefaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
    this.callbackExecutor = callbackExecutor;
  }

  @Override public @Nullable CallAdapter get(
      Type returnType, Annotation[] annotations, Retrofit retrofit) {
    
    final Type responseType = Utils.getParameterUpperBound(0, (ParameterizedType) returnType);

    // 这个 executor 取值为 callbackExecutor
    final Executor executor = Utils.isAnnotationPresent(annotations, SkipCallbackExecutor.class)
        ? null
        : callbackExecutor;

    return new CallAdapter>() {
      @Override public Type responseType() {
        return responseType;
      }

      @Override public Call adapt(Call call) {
        return executor == null
            ? call
            : new ExecutorCallbackCall<>(executor, call);
      }
    };
  }

    // ******
}
 
 

到这里我们算是找到底了,callAdapter 的实例,最终是在 DefaultCallAdapterFactory类的 get()方法创建出来的,也即是上面分析的 adapt() 抽象方法的实现。这个地方有点绕,现在问题转化为只需要分析 new ExecutorCallbackCall<>(executor, call)这么一行代码了。

先简单说明一下四个参数的意义,再往下进行:

  • requestFactory 是定义的 API 接口中方法的解析类
  • callFactory 其实就是 OkHttpClient 对象
  • responseConverter 是我们在构建 Retrofit 实例时,添加的转化工厂(暂不考虑 Retrofit 内置的转化工程类)
  • callAdapter 是将一个 Call对象(OkhttpCall) 适配成 okhttp3.Call 的一个适配器

重点分析 new ExecutorCallbackCall<>(executor, call),其中的 call 为 OkhttpCall,executor 是一个线程管理类,工作在主线程。

final class DefaultCallAdapterFactory extends CallAdapter.Factory {
  // ******

  static final class ExecutorCallbackCall implements Call {
    final Executor callbackExecutor;
    final Call delegate;  // 这个 delegate 实际上已经是 okhttp3.Call 了

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

    @Override public void enqueue(final Callback callback) {
      checkNotNull(callback, "callback == null");

      delegate.enqueue(new Callback() {
        @Override public void onResponse(Call call, final Response response) {
          
          // 注意这里,切到了主线程,然后把结果通过 callback 给回调到了外面,所以我们在外边写回调的时候,不用切线程,直接就更新 UI 了
          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 call, final Throwable t) {
          callbackExecutor.execute(new Runnable() {
            @Override public void run() {
              callback.onFailure(ExecutorCallbackCall.this, t);
            }
          });
        }
      });
    }

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

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

    // ***省略一些取消和请求的方法***
  }
}

当我们在外部调用 call.enqueue(**new** Callback>() {***});时,就会走 delegate.enqueue() 方法,切换到主线程之后再回调给外部的 callback,这个 delegate 其实就是 OkHttpCall,是在 HttpServiceMethod.invoke() 方法中实例化的。

再说一句,这个 OkHttpCall 内部维护了一个 okhttp3.Call,是在调用 delegate.enqueue() 的时候,通过 createRawCall() 来实例化的。由于 okhttp3.call请求是在子线程,所以 Retrofit 在内部帮我们把网络请求的响应结果切到了主线程,返回给了我们。

小总结吧:动态代理里边 invoke() 方法我的理解是,把 Retrofit 请求交给 invoke() 内部 adapt() 方法,将一个 Retrofit 类型的 Call 转变成了 okhttp3.Call对像,真正做事情的还是 okhttp。在响应数据返回的时候,retrofit 帮我们做了线程的切换。好了,Retrofit 的原理分析到此也就结束了,有些地方一点即过,可以去跟着翻翻源码。

你可能感兴趣的:(Retrofit 原理源码分析)