Retrofit2流程分析

Retrofit是Square公司出品的Http请求框架,底层网络模块基于Okhttp,是构造REST风格的HTTP客户端的利器,同时具备非常强大的解耦性,可以自定义多种数据格式(xml、json、protocol buffers等),支持Rxjava调用方式。
最近一直在看Retrofit2的源码,对于它具体的流程也是在多次调试后,才略微一二。下面主要分析下Rxjava接口形式的接口生成和调用流程。

Retrofit

Retrofit类是整个流程的入口通过它的Builder类设置一些基本的参数,如下:

 new Builder().baseUrl(baseUrl).addConverterFactory(factory).addCallAdapterFactory(RxJavaCallAdapterFactory.create());

ConverterFactory是Request和Response的转换类,继承Factory类,实现responseBodyConverter和requestBodyConverter即可。guava、gson、java8、protobuf等各种格式的converter可以参考官方文档。

Retrofit#create

通过create(final Class service)方法,将注解定义的接口生成一个具体的接口实现。接口定义方式如下:

public interface GitHubService {
@GET("users/{user}/repos")
Call> listRepos(@Path("user") String user);
}

如果使用Rxjava的话,可以定义如下:

public interface GitHubService {
 @GET("users/{user}/repos")
 Observable> listRepos(@Path("user") String user);
}

具体的create方法代码如下:

  public  T create(final Class service) {
    Utils.validateServiceInterface(service);
    if (validateEagerly) {
      eagerlyValidateMethods(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, 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);
            }
             ServiceMethod serviceMethod = loadServiceMethod(method);
            OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
            return serviceMethod.callAdapter.adapt(okHttpCall);
          }
        });
  }

它通过Proxy.newProxyInstance方法来一个实现了我们定义好的API接口的动态代理类,之后调用任何接口里面的方法,都会通过调用invoke(Object proxy, Method method, Object... args)方法来实现。

ServiceMethod

invoke方法最重要的是最后三行代码。loadServiceMethod方法先会判断缓存里面有没有该method对应的ServiceMethod,如果有就直接用,没有就会生成一个新的。

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

下面看下ServiceMethod的生成过程。

Adapts an invocation of an interface method into an HTTP call.

ServiceMethod 的作用就是把一个 API 方法转换为一个 HTTP 调用。

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

以上面的GitHubService中listRepos接口为例。

 public interface GitHubService {
  @GET("users/{user}/repos")
  Observable> listRepos(@Path("user") String user);
}

@GET("users/{user}/repos"是methodAnnotations,String是parameterTypes,@Path("user")是parameterAnnotationsArray的第一个,参数可以有多个,所有它是一个列表。

ServiceMathod#Builder.build()

public ServiceMethod build() {
      callAdapter = createCallAdapter();
      responseType = callAdapter.responseType();
      responseConverter = createResponseConverter();

      for (Annotation annotation : methodAnnotations) {
        parseMethodAnnotation(annotation);
      }

    parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
      }
      return new ServiceMethod<>(this);
    }

上面是build方法里面去除了异常处理之后的逻辑。

createCallAdapter

private CallAdapter createCallAdapter() {
    Type returnType = method.getGenericReturnType();
    
    Annotation[] annotations = method.getAnnotations();
      
    return retrofit.callAdapter(returnType, annotations);
    }

retrofit.callAdapter里面主要代码:

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

它根据returnType和annotations遍历adapterFactories,获取合适的CallAdapter。

/** * Returns an instance of {@code T} which delegates to {@code
call}. */ T adapt(Call call);

它的作用就是把 retrofit2.Call 转换成我们需要的 T,目前retrofit2.Call的实现只有OkHttpCall,所以现在Retrofit网络框架只能用OkHttp。CallAdapters

createCallAdapter

private Converter createResponseConverter() {
    Annotation[] annotations = method.getAnnotations();
    return retrofit.responseBodyConverter(responseType, 
    }
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;
      }
    }

它最后也是遍历converterFactories,获取合适的ResponseConverter,它一般是自定义的,通过Retrofit的Builder类addConverterFactory(factory)方法添加的。

parseMethodAnnotation

DELETE、GET、HEAD、PATCH、POST、PUT、OPTIONS这些注解会调用parseMethodAnnotation方法,生成httpMethod、hasBody、relativeUrl、relativeUrlParamNames4个ServiceMethod的参数,当注解是retrofit2.http.Headers类型时,会调用parseHeaders方法,它会生成OkHttp的Headers。

parseParameter

parseParameter方法通过参数的注解和类型,生成对应的ParameterHandler。

ParameterAnnotation ? extends ParameterHandler
Url RelativeUrl
Path Path
Query Query
QueryMap QueryMap
Header Header
HeaderMap HeaderMap
Field Field
FieldMap FieldMap
Part Part
PartMap PartMap
Body Body

所有类型的ParameterHandler都继承自ParameterHandler,实现了apply方法,通过Converter方法,把参数都转换成相应的类型,然后设置到RequestBuilder中,其中Part、PartMap、Body转成RequestBody,其他都转成String。

这样ServiceMethod基本构造完成。

OkHttpCall

之前我们说了,它是Retrofit中Call的唯一实现。

public interface Call

它负责发起请求和回复,每个Call只负责一对请求和回复,如果要复用的话,调用Call.clone方法。Call主要有execute和enqueue方法,前者是同步的,后者是异步的。OkHttpCall实现了Call接口,里面使用okhttp3.Call来完成网络服务交互。

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

createRawCall方法生成okhttp3.Call,request参数是通过serviceMethod的toRequest方法生成的。

execute和enqueue方法里面实际上就是调用okhttp3.Call来实现了同步和异步请求,但是对Response做了进一度处理,通过parseResponse方法,把OkHttp3.Response转成Retrofit2.Response

T body = serviceMethod.toResponse(catchingBody); return
Response.success(body, rawResponse);

T toResponse(ResponseBody body) throws IOException {
return responseConverter.convert(body); }

还是调用Retrofit里面的responseConverter实现了返回结果的转换。

serviceMethod.callAdapter.adapt(okHttpCall)

这一步是把Call转成我们所需的T。

CallAdapters ? extends CallAdapter.Factory T
guava retrofit2.adapter.guava.GuavaCallAdapterFactory com.google.common.util.concurrent.ListenableFuture
java8 retrofit2.adapter.java8.Java8CallAdapterFactory com.google.common.util.concurrent.ListenableFuture
rxjava retrofit2.adapter.rxjava.RxJavaCallAdapterFactory rx.Observable
default retrofit2.ExecutorCallAdapterFactory retrofit2.Call
default retrofit2.DefaultCallAdapterFactory retrofit2.Call

如果是retrofit2.Call类型的,可以调用execute或者enqueue完成请求。

如果rx.Observable类型,会在subscribe()时候调用下面代码:

@Override public void call(final Subscriber> subscriber) {
      // Since Call is a one-shot type, clone it for each new subscriber.
      Call call = originalCall.clone();

      // Wrap the call in a helper which handles both unsubscription and backpressure.
      RequestArbiter requestArbiter = new RequestArbiter<>(call, subscriber);
      subscriber.add(requestArbiter);
      subscriber.setProducer(requestArbiter);
    }

它其实是Observable.create(new CallOnSubscribe<>(call))里面CallOnSubscribe的实现。

你可能感兴趣的:(Retrofit2流程分析)