Retrofit 原理源码分析

作者: 拂晓是个小人物 | 来源:发表于2019-08-06 23:55 被阅读14次

    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<List<Repo>> 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<List<Repo>> call = gitHubApi.listRepos("octocat");
    
    call.enqueue(new Callback<List<Repo>>() {
        @Override
        public void onResponse(Call<List<Repo>> call, Response<List<Repo>> response) {
            mContentTextView.setText(response.body().get(0).getName() + " ");
        }
    
        @Override
        public void onFailure(Call<List<Repo>> call, Throwable t) {
            Log.e(TAG, "onFailure: " + t.toString());
        }
    });
    

    Retrofit 源码解析

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

    public interface Call<T> extends Cloneable {
      // ******
      void enqueue(Callback<T> callback);
    }
    
    // Retrofit#create()
    public <T> T create(final Class<T> 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<T> 中的抽象方法,等下贴出,那我们只能查看 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<T> {
      static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
        
        // 这个 RequestFactory 里边存放的是:1.我们在 API 接口里边定义的方法的全部信息,包括方法的返回值,
        // 方法的参数和方法的注解信息; 2.通过 Builder 模式构造Retrofit实例时,组装的参数,如 baseUrl 信息等
        RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);
    
        // ******
        // HttpServiceMethod.parseAnnotations()调用的是一个静态方法,该方法返回值是 ServiceMethod<T>,
        // 由下一步的查看源码可以知道,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<ResponseT, ReturnT> extends ServiceMethod<ReturnT> {
        // ....
      @Override final @Nullable ReturnT invoke(Object[] args) {
      Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
        return adapt(call, args);
        }
    
        protected abstract @Nullable ReturnT adapt(Call<ResponseT> call, Object[] args);
        // ***
    }
    
    // 这里通过 requestFactory,args,callFactory,和 responseConverter 几个参数,创建了一个新的 OkHttpCall,
    // 至于上边几个参数什么意思,等下就会分析到
    // 最终 invoke() 调用抽象方法 adapt(),其中 call 就是创建的 OkHttpCall,我们只要找到 adapt() 的实现的地方即可,这里暂且放下
    

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

    // HttpServiceMethod#ParseAnnotations()  经过精简后的代码
    static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
        Retrofit retrofit, Method method, RequestFactory requestFactory) {
      boolean isKotlinSuspendFunction = requestFactory.isKotlinSuspendFunction;
      Annotation[] annotations = method.getAnnotations();
      Type adapterType;
      if (isKotlinSuspendFunction) {
        // ******
      } else {
        adapterType = method.getGenericReturnType();
      }
    
      CallAdapter<ResponseT, ReturnT> callAdapter =
          createCallAdapter(retrofit, method, adapterType, annotations);
      Type responseType = callAdapter.responseType();
      // ******
    
      Converter<ResponseBody, ResponseT> 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<ResponseT, ReturnT> extends ServiceMethod<ReturnT> {
        // ******
      static final class CallAdapted<ResponseT, ReturnT> extends HttpServiceMethod<ResponseT, ReturnT> {
        private final CallAdapter<ResponseT, ReturnT> callAdapter;
    
        CallAdapted(RequestFactory requestFactory, okhttp3.Call.Factory callFactory,
          Converter<ResponseBody, ResponseT> responseConverter,
          CallAdapter<ResponseT, ReturnT> callAdapter) {
           super(requestFactory, callFactory, responseConverter);
           this.callAdapter = callAdapter;
         }
    
        @Override protected ReturnT adapt(Call<ResponseT> 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<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
      callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));
    
      // Make a defensive copy of the converters.
      List<Converter.Factory> 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 <T> Converter<ResponseBody, T> 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<ResponseBody, ?> converter =
            converterFactories.get(i).responseBodyConverter(type, annotations, this);
        if (converter != null) {
          //noinspection unchecked
          return (Converter<ResponseBody, T>) converter;
        }
      }
        // ******
    }
    
    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl("https://api.github.com")
            .addConverterFactory(GsonConverterFactory.create()) //将响应数据,转化为对应的bean的转化工厂
            .build();
    

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

    
    Type adapterType = method.getGenericReturnType();
    CallAdapter<ResponseT, ReturnT> 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<CallAdapter.Factory> 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<Object, Call<?>>() {
          @Override public Type responseType() {
            return responseType;
          }
    
          @Override public Call<Object> adapt(Call<Object> 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<T> implements Call<T> {
        final Executor callbackExecutor;
        final Call<T> delegate;  // 这个 delegate 实际上已经是 okhttp3.Call 了
    
        ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
          this.callbackExecutor = callbackExecutor;
          this.delegate = delegate;
        }
    
        @Override public void enqueue(final Callback<T> callback) {
          checkNotNull(callback, "callback == null");
    
          delegate.enqueue(new Callback<T>() {
            @Override public void onResponse(Call<T> call, final Response<T> 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<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();
        }
    
        @Override public Response<T> execute() throws IOException {
          return delegate.execute();
        }
    
        // ***省略一些取消和请求的方法***
      }
    }
    

    当我们在外部调用 call.enqueue(**new** Callback<List<Repo>>() {***});时,就会走 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 原理源码分析

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