Retrofit源码解析-重点整理

Retrofit源码解析

基于Retrofit2.7.1

implementation 'com.squareup.retrofit2:retrofit:2.7.1'
implementation 'com.squareup.retrofit2:converter-gson:2.7.1'

Retrofit的基本使用

val retrofit = Retrofit.Builder()
    .baseUrl("https://api.github.com")
    .addConverterFactory(GsonConverterFactory.create())
    .build()

val service = retrofit.create(GitHubService::class.java)
val repos: Call<List<Repo>> = service.listRepos("octocat")

repos.enqueue(object : Callback<List<Repo>?> {
    override fun onFailure(call: Call<List<Repo>?>, t: Throwable) {

    }

    override fun onResponse(call: Call<List<Repo>?>, response: Response<List<Repo>?>) {

    }
})

retrofit.create

首先来看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);
	    }
	    if (platform.isDefaultMethod(method)) {
	      return platform.invokeDefaultMethod(method, service, proxy, args);
	    }
	    return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
	  }
	});
}
validateServiceInterface

在validateServiceInterface中,会去检查GitHubService.class写的是否正确,如果不正确会抛出异常。

并且会将所有GithubService.class中的方法预先加载到缓存中

private void validateServiceInterface(Class<?> service) {
    if (!service.isInterface()) { //检查是否是接口
      throw new IllegalArgumentException("API declarations must be interfaces.");
    }

    Deque<Class<?>> check = new ArrayDeque<>(1);
    check.add(service);
    while (!check.isEmpty()) {
      Class<?> candidate = check.removeFirst();
      if (candidate.getTypeParameters().length != 0) { //检查是否有泛型
        StringBuilder message = new StringBuilder("Type parameters are unsupported on ")
            .append(candidate.getName());
        if (candidate != service) {
          message.append(" which is an interface of ")
              .append(service.getName());
        }
        throw new IllegalArgumentException(message.toString());
      }
      Collections.addAll(check, candidate.getInterfaces());
    }

    if (validateEagerly) { //如果配置了validateEagerly,会检查接口方法编写是否正确
      Platform platform = Platform.get();
      for (Method method : service.getDeclaredMethods()) {
        if (!platform.isDefaultMethod(method) && !Modifier.isStatic(method.getModifiers())) {
          loadServiceMethod(method);
        }
      }
    }
  }

PS: 由此可知,在实际使用中,可以在生产环境中设置validateEagerly为false,来加快初始化速度,测试环境中,设置validateEagerly为true,来更快地暴露问题。

Proxy.newProxyInstance

再接下来看具体创建

//动态代理
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 {
        // Object的方法直接调用原方法
        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);
      }
    });

这里采用了动态代理,这里主要来看loadServiceMethod(method).invoke(args != null ? args : emptyArgs);

来看loadServiceMethod

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

可以看到,这里主要就用到了一个缓存。如果serviceMethodCache里有就直接返回,如果没有,那么解析这个method,保存到serviceMethodCache中。

而invoke实际调用的时HttpServiceMethod.invoke

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

所以,我们在执行repos.enqueue的时候,实际是在执行OkHttpCall.enqueue

Override public void enqueue(final Callback<T> callback) {
	Objects.requireNonNull(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 {
	      call = rawCall = createRawCall();
	    } catch (Throwable t) {
	      throwIfFatal(t);
	      failure = creationFailure = t;
	    }
	  }
	}
	
	if (failure != null) {
	  callback.onFailure(this, failure);
	  return;
	}
	
	if (canceled) {
	  call.cancel();
	}
	
	call.enqueue(new okhttp3.Callback() {
	  @Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {
	    Response<T> response;
	    try {
	      response = parseResponse(rawResponse);
	    } catch (Throwable e) {
	      throwIfFatal(e);
	      callFailure(e);
	      return;
	    }
	
	    try {
	      callback.onResponse(OkHttpCall.this, response);
	    } catch (Throwable t) {
	      throwIfFatal(t);
	      t.printStackTrace(); // TODO this is not great
	    }
	  }
	
	  @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) {
	      throwIfFatal(t);
	      t.printStackTrace(); // TODO this is not great
	    }
	  }
	});
}

这里调用okhttp的call.enqueue,并在onResponse中,通过parseResponse解析成Response,即,Retrofit只是对OkHttp封装了一层。

线程切换

我们回到HttpServiceMethod.invoke方法

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

可以看到这里还有行adapt(call, args),这里最终在DefaultCallAdapterFactory

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

这里的executor,是在Retrofit构建的时候,就创建的。
Retorift#build

public Retrofit build() {
      if (baseUrl == null) {
        throw new IllegalStateException("Base URL required.");
      }

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

可以看到,executor就是platform.defaultCallbackExecutor

static final class Android extends Platform {
    Android() {
      super(Build.VERSION.SDK_INT >= 24);
    }

    @Override public Executor defaultCallbackExecutor() {
      return new MainThreadExecutor();
    }

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

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

即,线程切换就是调用了主线程的Handler。

为什么这么设计 ?
因为这样不仅可以用来切换线程,还可以用来干别的事情。

我们也可以通过addCallAdapterFactory来添加相应的Adapter,比如转换为RxJava,
同时,我们也可以通过addConverterFactory来添加需要的转换器。

OkHttp.call是怎么创建出来的

通过requestFactoryequestFactory.create创建okhttp的请求并发起请求。

(rawCall = createRawCall()).request();

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

而请求的参数,是在loadServiceMethod> ServiceMethod.parseAnnotations > equestFactory.parseAnnotations > RequestFactory.build中就进行了解析的

收到结果后是怎么解析的

来看OkHttpCall#parseResponse

Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
    ResponseBody rawBody = rawResponse.body();

    // Remove the body's source (the only stateful object) so we can pass the response along.
    rawResponse = rawResponse.newBuilder()
        .body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength()))
        .build();

    int code = rawResponse.code();
    if (code < 200 || code >= 300) {
      try {
        // Buffer the entire body to avoid future I/O.
        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);
    }

    ExceptionCatchingResponseBody catchingBody = new ExceptionCatchingResponseBody(rawBody);
    try {
      T body = responseConverter.convert(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;
    }
  }

判断code之后,会调用responseConverter.convert(catchingBody);,通过responseConverter进行解析,比如GsonConverterFactory。

来看下GsonConverterFactory

@Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
    Retrofit retrofit) {
  TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
  return new GsonResponseBodyConverter<>(gson, adapter);
}

本文基于Retrofit2.7.1

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

氦客

你的鼓励是我创作最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值