美文网首页
Retrofit2流程分析

Retrofit2流程分析

作者: TutuJie | 来源:发表于2017-06-24 23:32 被阅读0次

    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<T> service)方法,将注解定义的接口生成一个具体的接口实现。接口定义方式如下:

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

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

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

    具体的create方法代码如下:

      public <T> T create(final Class<T> 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<List<Repo>> 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}. */ <R> T adapt(Call<R> call);

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

    createCallAdapter

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

    它最后也是遍历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<T>

    它负责发起请求和回复,每个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<R>
    default retrofit2.DefaultCallAdapterFactory retrofit2.Call<R>

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

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

    @Override public void call(final Subscriber<? super Response<T>> subscriber) {
          // Since Call is a one-shot type, clone it for each new subscriber.
          Call<T> call = originalCall.clone();
    
          // Wrap the call in a helper which handles both unsubscription and backpressure.
          RequestArbiter<T> requestArbiter = new RequestArbiter<>(call, subscriber);
          subscriber.add(requestArbiter);
          subscriber.setProducer(requestArbiter);
        }
    

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

    相关文章

      网友评论

          本文标题:Retrofit2流程分析

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