拆一拆Retrofit

用力拆一拆Retrofit

Retrofit是什么?

A type-safe HTTP client for Android and Java

一个应用于Android和Java类型安全的HTTP客户端(OkHttp的自我介绍是:OkHttp is an HTTP client that’s efficient by default;一个高效的HTTP客户端,当然Retrofit内部已经集成了OkHttp用于实际的网络请求,所以他也可以说是HTTP客户端了)

Retrofit的使用方法

  1. 创建一个Interface作为Web Service的请求集合,以注解(annotation)的形式添加请求方法的配置。
public interface NetWorkService {
	@GET("users/{user}/repos")
	Call<List<Repo>> listRepos(@Path("user") String user);
}
  1. 用Retrofit创造Interface的实例对象。
Retrofit retrofit = new Retrofit.Builder()
 .baseUrl("https://api.github.com/")v
 .build();
NetWorkService service =
retrofit.create(NetWorkService);
  1. 调用实例的方法并创建出相应的网路请求Call。
Call<List<Repo>> repos = service.listRepos("maidong");
  1. 使用Call.execute()或Call.enqueue()方法发起网络请求。
repos.enqueue(callback);

功能拆解

通过Retrofit.create()创建出Web Interface的实例对象,从而使得Interface的方法变得可用。

Retrofit的create做了什么?

  public <T> T create(final Class<T> service) {
    validateServiceInterface(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);
                }
                args = args != null ? args : emptyArgs;
                return platform.isDefaultMethod(method)
                    ? platform.invokeDefaultMethod(method, service, proxy, args)
                    : loadServiceMethod(method).invoke(args);
              }
            });
  }

Proxy.newProxyInstance会根据Interface(参数二,一般只有一个Interface,是我们调用Retrofit.create(ServiceIntetface.class)传进来的)创建一个实现类,该类实现了Ineteface的所有方法(代理了Inteface中定义的方法)。并且每个方法都会调用该类的成员变量InvocationHandler的invoce方法(Proxy.newProxyInstance的参数三)并且会把自己的方法信息传给invoke。

所以真正做事的是invoke方法,所以当service.listRepos(“maidong”);执行时就会调用invoke中的方法,其中关键代码只有一行 :

loadServiceMethod(method).invoke(args);

这行代码分可为两个关键方法:

  1. loadServiceMethod(method);
  2. invoke(args);

下面分别来看。

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;
  }


  static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
      Retrofit retrofit, Method method, RequestFactory requestFactory) {
    boolean isKotlinSuspendFunction = requestFactory.isKotlinSuspendFunction;
    boolean continuationWantsResponse = false;
    boolean continuationBodyNullable = false;

    Annotation[] annotations = method.getAnnotations();//获取方法中的注解,进行分析和初步的处理
    Type adapterType;
    if (isKotlinSuspendFunction) {
      Type[] parameterTypes = method.getGenericParameterTypes();
      Type responseType =
          Utils.getParameterLowerBound(
              0, (ParameterizedType) parameterTypes[parameterTypes.length - 1]);
      if (getRawType(responseType) == Response.class && responseType instanceof ParameterizedType) {
        // Unwrap the actual body type from Response<T>.
        responseType = Utils.getParameterUpperBound(0, (ParameterizedType) responseType);
        continuationWantsResponse = true;
      } else {
        // TODO figure out if type is nullable or not
        // Metadata metadata = method.getDeclaringClass().getAnnotation(Metadata.class)
        // Find the entry for method
        // Determine if return type is nullable or not
      }

      adapterType = new Utils.ParameterizedTypeImpl(null, Call.class, responseType);
      annotations = SkipCallbackExecutorImpl.ensurePresent(annotations);
    } else {
      adapterType = method.getGenericReturnType();
    }

    CallAdapter<ResponseT, ReturnT> callAdapter =
        createCallAdapter(retrofit, method, adapterType, annotations);
    Type responseType = callAdapter.responseType();
    if (responseType == okhttp3.Response.class) {
      throw methodError(
          method,
          "'"
              + getRawType(responseType).getName()
              + "' is not a valid response body type. Did you mean ResponseBody?");
    }
    if (responseType == Response.class) {
      throw methodError(method, "Response must include generic type (e.g., Response<String>)");
    }
    // TODO support Unit for Kotlin?
    if (requestFactory.httpMethod.equals("HEAD") && !Void.class.equals(responseType)) {
      throw methodError(method, "HEAD method must use Void as response type.");
    }

    Converter<ResponseBody, ResponseT> responseConverter =
        createResponseConverter(retrofit, method, responseType);

    okhttp3.Call.Factory callFactory = retrofit.callFactory;
    if (!isKotlinSuspendFunction) {//如果不是挂起函数,创建并返回一个CallAdapter
      return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
    } else if (continuationWantsResponse) {
	....
    } else {
    .....  
  }

上述源码很多,主要是进行注解的解析和初步处理,并且返回一个CallAdapter对象。稍后会介绍什么CallAdapter。我们继续…
接下来会调用invoke方法,先看源码:

  @Override
  final @Nullable ReturnT invoke(Object[] args) {
    Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
    return adapt(call, args);
  }

  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);//返回的是一个OkHttp.call,接下来会分析。
    }
  }

上述代码最终返回的是callAdapter.adapt(call),也就是Call<List> repos = service.listRepos(“maidong”);左边这部分。从结果来看callAdapter.adapt(call)是个Call,那么接下来我们看看callAdapter.adapt做了什么事情,以及callAdapter是个啥,从哪来的?

CallAdapter是什么?

CallAdapter是CallAdapter.Factory的子类,是一个工厂类,如果我们设置了自定义的callAdapter这里也会生成其他类型的对象,如RxJava会最终生成Observable对象。

如果没单独配置的话,Retrofit会默认添加一个CallAdapter–DefaultCallAdapterFactory


      // 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));

  List<? extends CallAdapter.Factory> defaultCallAdapterFactories(
      @Nullable Executor callbackExecutor) {
    DefaultCallAdapterFactory executorFactory = new DefaultCallAdapterFactory(callbackExecutor);
    return hasJava8Types
        ? asList(CompletableFutureCallAdapterFactory.INSTANCE, executorFactory)
        : singletonList(executorFactory);
  }


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

  DefaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
    this.callbackExecutor = 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);
      }
    };
  }

所以默认下,invoke方法中调用的adapt的实际的实现是:return executor == null ? call : new ExecutorCallbackCall<>(executor, call);
返回值类型是 Call。

因为上述代码中DefaultCallAdapterFactory创建时有传executor,所以我们接着看ExecutorCallbackCall是个啥。


  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) {
      Objects.requireNonNull(callback, "callback == null");

      delegate.enqueue(
          new Callback<T>() {
            @Override
            public void onResponse(Call<T> call, final Response<T> response) {
              callbackExecutor.execute(
                  () -> {
                    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(() -> callback.onFailure(ExecutorCallbackCall.this, t));
            }
          });
    }

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

    @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();
    }

    @Override
    public Timeout timeout() {
      return delegate.timeout();
    }
  }

是不是很熟悉,哈哈哈
所以service.listRepos(“maidong”)最终返回的是ExecutorCallbackCall。

还记得这个方法吗?

repos.enqueue(callback);

我们现在就很清楚的知道调用的是ExecutorCallbackCall里的enqueue方法。
接下来看下callbackExecutor是什么,是的,没错它就是创建DefaultCallAdapterFactory时一路传过来的Exector,线程池管理类,借助它可以实现线程切换到主线程,然后把网络响应结果交回给 Retrofit 的
Callback 。
接下来看看Retrofit是怎么实现的线程切换:

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

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

是通过Handler和主线程进行绑定,利用post发送到主线程中从而实现线程切换。

完结。

上一篇:Retrofit踩坑之Delete请求


下一篇:Retrofit实现网络请求