美文网首页源码解析
retrofit源码解析

retrofit源码解析

作者: telyo | 来源:发表于2018-01-23 17:31 被阅读0次

    Retrofit 是当下android开发最流行的网络请求框架。用了Retrofit体会到了它的强大之处一直对它的内部实现很感兴趣,花了两天的时间研究了一下它的源码,虽然对里面的设计模式,和为什么要这么做说不出个所以然来,但还是把Retrofit的整个流程搞清楚了。接下来就是记录了一下解析的过程。尽量的写详细点.........

    一、retrofit的创建源码解析

    众所周知retrofit的创建是用builder模式创建的,最后就是初始化Retrofit里面所需要的成员对象:一个callFactory其实就是OkHttpClient;还有两个factory容器,这里就是工厂模式,分别用来生产解析请求结果(Json数据),和适配网络求情的CallAdapter.

     Retrofit(okhttp3.Call.Factory callFactory, BaseUrl baseUrl,
          List<Converter.Factory> converterFactories, List<CallAdapter.Factory> adapterFactories,
          Executor callbackExecutor, boolean validateEagerly) {
        this.callFactory = callFactory;
        this.baseUrl = baseUrl;
        this.converterFactories = converterFactories;
        this.adapterFactories = adapterFactories;
        this.callbackExecutor = callbackExecutor;
        this.validateEagerly = validateEagerly;
      }
    

    按照源码注释来使用Retrofit就是:

    For example,
    <pre>{@code
    Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("http://api.example.com")
        .addConverterFactory(GsonConverterFactory.create())
        .build();
    MyApi api = retrofit.create(MyApi.class);
    Response<User> user = api.getUser().execute();
    }</pre>
    

    可以看到创建一个retrofit一般只需要在builder里传入baseUrl和一个GsonConverterFactory因为其他的参数都有默认值,如果不修改就采用默认值了。而且默认值都是在在Builder 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();
          }
    
          // Make a defensive copy of the adapters and add the default Call adapter.默认的含有CallAdapter。Factory的容器
          List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
          adapterFactories.add(Platform.get().defaultCallAdapterFactory(callbackExecutor));
    
          // Make a defensive copy of the converters.
          List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);
    
          return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
              callbackExecutor, validateEagerly);
        }
    

    看,除了一个baseUrl必传入之外,其它的参数要么有默认的初始化要么可以不用传值:

    • okhttp3.Call.Factory callFactory 可以猜到这个是用来进行网络请求的,如果不传入的话,默认的也是用 new OkHttpClient() 来进行初始化;
    • List<CallAdapter.Factory> adapterFactories在Build里申明的时候就已经初始化为一个ArrayList,Bulid在设置CallAdapter的时候只是向里面添加CallAdapter,并且里面一开始就添加了默认的CallAdapterFactory:一个DefaultCallAdapterFactory的对象
    /**
         * Add a call adapter factory for supporting service method return types other than {@link
         * Call}.
         */
        public Builder addCallAdapterFactory(CallAdapter.Factory factory) {
          adapterFactories.add(checkNotNull(factory, "factory == null"));
          return this;
        }
    

    所以Retrofit应该可以支持多个CallAdapter,这个在后面解析过程中再看是用来做什么的吧!

    • 最后是List<Converter.Factory> converterFactories 其实也和List<CallAdapter.Factory> adapterFactories 一样,不过没有往里面加入默认值(猜一下它的作用:它是用来解析Json用的吧)。所以创建一个Retrofit至少就要用:
    Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("http://api.example.com")
        .addConverterFactory(GsonConverterFactory.create())
        .build();
    
    • 最后的是一个boolean 值:validateEagerly(java中boolean的值都是false,当然也可以不用我们去初始化), 看一下代买的英文注释:
    /**
         * When calling {@link #create} on the resulting {@link Retrofit} instance, eagerly validate
         * the configuration of all methods in the supplied interface.
         */
    

    翻译过来就是 :创建完Retrofit的实例后,当去调用它的create方法时,一开始就(急切的)让这个接口(最后的Service)的方法变得合法化(不管你后面的代理对象能不能创建成功)。(个人理解)还是不懂请看下文

    二、Retrofit的使用源码解析

    创建好了Retrofit,那我们当然是要调用它的Api了,其实它的Api也就一个:<T> T create(final Class<T> service),就是这个方法。它的作用就是用动态代理模式,产生一个代理对象,可以用这个代理对象替我们完成网络请求,并返回结果。看看代码是怎么写的吧:

    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);
                }
                return loadMethodHandler(method).invoke(args);
              }
            });
      }
      
    
    1、判断service类型

    一进入这个方法里首先会对service的类型做判断: Utils.validateServiceInterface(service);

    static <T> void validateServiceInterface(Class<T> service) {
        if (!service.isInterface()) {
          throw new IllegalArgumentException("API declarations must be interfaces.");
        }
        // Prevent API interfaces from extending other interfaces. This not only avoids a bug in
        // Android (http://b.android.com/58753) but it forces composition of API declarations which is
        // the recommended pattern.
        if (service.getInterfaces().length > 0) {
          throw new IllegalArgumentException("API interfaces must not extend other interfaces.");
        }
      }
    

    如果service不是接口类型或者service实现了某个接口都会在编译时报错!

    2、是否需要提前使方法合理化
    if (validateEagerly) {
          eagerlyValidateMethods(service);
        }
    

    这个是上面解析创建时validateEagerly参数初始化的遗留问题,它的作用也就在这一行代码里(决定是否需要提前使方法合理化,具体为什么要这样设计,我也不太清楚),这个eagerlyValidateMethods()方法里面最后调用了loadMethodHandler(method),因为动态代理的时候也会调用,所以这个合理化接口的方法的作用留到后面解释。

    3、生成动态代理对象

    动态代理这个就不说了吧,如果不了解就可以google或百度一下,return就是一个动态代理对象。动态代理对象调用它的方法返回的是return method.invoke(this, args);当然里面做了判断:

     if (method.getDeclaringClass() == Object.class) {
                  return method.invoke(this, args);
                }
    

    如果传入的final Class<T> service 是一个Object.class 的话才按照正常的返回,这个呢对动态代理有过了解的应该可能会知道,正常返回意味着什么了(这个返回就是调用代理对象的方法的返回,可以是null但是一定会执行方法)。

    这里只对不正常返回做解释了。因为create方法一开始就指定service必须是interface:

    MyApi api = retrofit.create(MyApi.class);
    Response<User> user = api.getUser().execute();
    

    这里的MyApi是一个接口interface类型的(这里就不是Object了)所以method.getDeclaringClass() == Object.class 会返回false。再往下走:

     if (platform.isDefaultMethod(method)) {
                  return platform.invokeDefaultMethod(method, service, proxy, args);
                }
    

    这个platform.isDefaultMethod(method)方法(和java8.0有关吧),不过源码写死的返回false:

      boolean isDefaultMethod(Method method) {
        return false;
      }
    

    那就不管了再往下走,就是关键代码返回了:

     return loadMethodHandler(method).invoke(args);
    
    1. loadMethodHandler(method)使方法合理化(传入的是一个interface的class对象,interface的方法都没有被实现,当然“不合法”):确定代理对象里包含的的方法名称(当然和接口的方法名称是一样的)+通过解析注释来确定代理对象的这个方法具体要做些什么(当然是网络请求返回结果)。
    2. invoke(args):传入代理对象调用代理对象的方法时需要的参数(进行网络请求的参数)如果代理对象调用了它的方法(进行网络请求),就会返回一个OkHttpCall<>对象(用来进行网络请求:execute());

    到这里,这个代理对象的创建也完成了,接下来就是调用的对象的方法,完成网络的请求任务并返回结果了,就像下面使用的代码那样:

    MyApi api = retrofit.create(MyApi.class);
    Response<User> user = api.getUser().execute();
    

    三、动态代理对象方法调用的原理解析

    动态代理对象创建完成时,就可以直接调用它的方法完成相应的任务,那么Retrofit的内部是怎么实现让这个代理对象具备这样的能力的呢?

    接到Retrofit的create方法里的最后一行代码看:

    return loadMethodHandler(method).invoke(args);
    

    首先我们看一下loadMethodHandler(method)做了什么事情:

     MethodHandler loadMethodHandler(Method method) {
        MethodHandler handler;
        synchronized (methodHandlerCache) {
         ...
          if (handler == null) {
            handler = MethodHandler.create(this, method);
           ...
          }
        }
        return handler;
      }
    

    它就是创建并返回了一个MethodHandler 对象,先看一看MethodHandler 对我们传入的方法做了些什么,才使得传入的方法“合法化”了呢。

    首先创建MethodHandler的代码(调用MethodHandler的静态方法create):

     handler = MethodHandler.create(this, method);
    

    这里传入了retrofit本身的实例化对象,和service的方法method对象;下面是create方法的具体内容:

     static MethodHandler create(Retrofit retrofit, Method method) {
        CallAdapter<?> callAdapter = createCallAdapter(method, retrofit);
        Type responseType = callAdapter.responseType();
        if (responseType == Response.class || responseType == okhttp3.Response.class) {
          throw Utils.methodError(method, "'"
              + Types.getRawType(responseType).getName()
              + "' is not a valid response body type. Did you mean ResponseBody?");
        }
        Converter<ResponseBody, ?> responseConverter =
            createResponseConverter(method, retrofit, responseType);
        RequestFactory requestFactory = RequestFactoryParser.parse(method, responseType, retrofit);
        return new MethodHandler(retrofit.callFactory(), requestFactory, callAdapter,
            responseConverter);
      }
    

    先看看new MethodHandler()里需要4个参数:

     MethodHandler(okhttp3.Call.Factory callFactory, 
                        RequestFactory requestFactory,
                        CallAdapter<?> callAdapter, 
                        Converter<ResponseBody, ?> responseConverter)
    

    这4个参数基本上是在MethodHandler 的静态方法里creat()进行初始化的,先看看 CallAdapter<?>初始化吧!

    1、用Retrofit的最后一个CallAdapterFactory创建CallAdapter

    从这里开始呢,方法“合法化”的操作就会正式开始了,首先创建callAdapter ,先别管他是用来干嘛的,先看看具体实现。通过createCallAdapter(method, retrofit)来创建具体实现是:

     private static CallAdapter<?> createCallAdapter(Method method, Retrofit retrofit) {
        Type returnType = method.getGenericReturnType();
        if (Utils.hasUnresolvableType(returnType)) {
          throw Utils.methodError(method,
              "Method return type must not include a type variable or wildcard: %s", returnType);
        }
        if (returnType == void.class) {
          throw Utils.methodError(method, "Service methods cannot return void.");
        }
        Annotation[] annotations = method.getAnnotations();
        try {
          return retrofit.callAdapter(returnType, annotations);
        } catch (RuntimeException e) { // Wide exception range because factories are user code.
          throw Utils.methodError(e, method, "Unable to create call adapter for %s", returnType);
        }
      }
    
    1. 检查method的返回值(method.getGenericReturnType())。为泛型和通配符或者为空,编译都不会通过
    2. 以列表的形式获取method的注解annotations(这个最终好像没有用到),最终才调用retrofit的callAdapter()方法,该方法又会继续调用retrofit的nextCallAdapter()方法: return nextCallAdapter(null, returnType, annotations);,由于该方法过长就不贴全部了,关键代码如下:
    public CallAdapter<?> nextCallAdapter(CallAdapter.Factory skipPast, Type returnType,Annotation[] annotations) {
       ...
        int start = adapterFactories.indexOf(skipPast) + 1;
        for (int i = start, count = adapterFactories.size(); i < count; i++) {
          CallAdapter<?> adapter = adapterFactories.get(i).get(returnType, annotations, this);
          if (adapter != null) {
            return adapter;
          }
        }
      ...
      }
    

    skipPast传入的是一个空对象不用管

    adapterFactories还记得吧!就是构建retrofit的时候build()方法里初始化的,而且还自动添加了一个默认的CallAdapterFactory:

     adapterFactories.add(Platform.get().defaultCallAdapterFactory(callbackExecutor));
    

    那么从nextCallAdapter()方法可以看出,返回的就是adapterFactories容器里的最后一个CallAdapterFactory对象调用get方法所创建的CallAdapter对象了。

    看一下实现了CallAdapter.Factory这个接口的DefaultCallAdapterFactory是怎么写的创建方法的:

     @Override
      public CallAdapter<?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
     ...
        final Type responseType = Utils.getCallResponseType(returnType);
        return new CallAdapter<Call<?>>() {
          @Override public Type responseType() {
            return responseType;
          }
    
          @Override public <R> Call<R> adapt(Call<R> call) {
            return call;
          }
        };
      }
    

    直接返回了匿名实现的CallAdapter<Call<?>>,其实这里就是一个适配器模式(其他调用者必须将用于网络请求的对象转换成一个Call<R>对象)

    @Override public <R> Call<R> adapt(Call<R> call)这个方法的实现就是返回的一个Call实例,用于做网络请求的。

    2、生成用来作网络请求的实例:OkhttpOkHttpCall<>

    好了到了这里我们先不去看new MethodHandler()的其他几个参数具体是怎样初始化的,因为还记得retorfit的create()方法吗?最后一句:

     return loadMethodHandler(method)
                        .invoke(args);
    

    现在我们loadMethodHandler(method)就告一段落了,其他的几个参数到后面在具体解析(这个方法就是用来创建MethodHandler的实例的)。接下来看一下MethodHandler的invoke(args)做了什么:

    Object invoke(Object... args) {
        return callAdapter.adapt(
            new OkHttpCall<>(callFactory, requestFactory, args, responseConverter));
      }
    

    invoke方法将已经实例化的callAdapter的adapt方法传入的 new OkHttpCall<>作为返回。

    小结

    现在就可以基本对Retrofit的网络请求实现原理写一个结论出来:

    1. 通过build模式创建一个Retrofit
    2. 调用创建出的retorfit的create方法(动态代理模式)创建代理对象
    3. (被代理对象是一个interfafe)所以要通过MethodHandler,使方法“合理化”(主要是解析注解和构建request,下面的分析会讲到)。
    4. 如果在构建retrofit时,没有对addCallAdapterFactory做配置就会采用默认的DefaultCallAdapterFactory生成Call适配器,那么代理对象调用方法的返回值,也就是invoke方法的返回,是通过callAdapter.adapt()的返回,其实最终就是一个继承了Call<>的OkHttpCall<>了。

    例如

    MyApi api = retrofit.create(MyApi.class);
     * Response<User> user = api.getUser().execute();
    

    这里的MyApi api就是被这个生成的代理对象赋值,代理对象和被代理对象拥有同名方法getUser(),这里的这个getUser()方法返回值就是MethodHandler.invok()的返回值OkHttpCall<>了。execute()就是OkHttpCall<>里面的网络请求的方法。

    四、OkHttpCall<>对象

    execute()的具体实现这里先不去分析,有几个网络请求的问题先捋一捋:

    1. 网络请求方法所需要的参数怎么传进去的(其实就是args),是怎么处理这些参数的?
    2. 一个网络请求的链接怎么拼接的?
    3. 怎么判断用GET还是用POST?
    4. ...

    其实这些都是通过对Annotation(注解)的解析实现的,既然最后都是用OkHttpCall<>的具体对象来做的网络请求,那这一部分就主要探寻OkHttpCall<>前世今生吧!

    1、OkHttpCall<>的创建

    OkHttpCall<>第一次被创建的地方就是在MethodHandler里初始化的callAdapter的adapt方法里。

    new MethodHandler()所需要的4个参数除了callAdapter,其他三个参数都是用来创建OkHttpCall<>对象的,当然创建OkHttpCall<>对象也需要4个参数:

     OkHttpCall(okhttp3.Call.Factory callFactory,
                         RequestFactory requestFactory, 
                         Object[] args,
                        Converter<ResponseBody, T> responseConverter) 
    

    args,就是通过动态代理得到的method方法里所需要的参数的一个列表,在调用MethodHandler的invoke方法时传入(参考源码或者上一章Retrofit的creat()和MethodHandler部分的代码)。
    而其他的三个参数都要通过MethodHandler的静态方法 create()里传入的retorfit对象获得。以下是三个参数的初始化方式:

    1. callFactory:
    retrofit.callFactory();
    
    1. responseConverter :
    Converter<ResponseBody, ?> responseConverter =
            createResponseConverter(method, retrofit, responseType);
    
    1. requestFactory:
     RequestFactory requestFactory = RequestFactoryParser.parse(method, responseType, retrofit);
    

    因为OkHttpCall<>没有对method的注解做任何操作,所以method的注解的解析操作就与requestFactory或者responseConverter有关了。

    callFactory:

    retrofit.callFactory()返回的就是一个OkHttpClient对象,这个在构建Retrofit的章节说过。

    responseConverter :

    responseConverter的初始化与callAdapter的初始化类似最终调用了retrofit的nextRequestBodyConverter关键代码:

     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没有设置,就会拿到默认的工厂实例。并用这个工厂实例创建一个Converter<ResponseBody, ?>的实例

    当然看到这个converterFactories是不是也很熟悉呢?没错这家伙在Retrofit.Build里被初始化的同时也加入了一个默认的Converter.Factory的实例(在Retrofit.Build的构造方法里):

     public Builder() {
          // 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());
        }
    

    好,那么我们看看这里是怎么样创建Converter<ResponseBody, ?>实例的方法:

     @Override
      public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
          Retrofit retrofit) {
        if (type == ResponseBody.class) {
          if (Utils.isAnnotationPresent(annotations, Streaming.class)) {
            return StreamingResponseBodyConverter.INSTANCE;
          }
          return BufferingResponseBodyConverter.INSTANCE;
        }
        if (type == Void.class) {
          return VoidResponseBodyConverter.INSTANCE;
        }
        return null;
      }
    

    看看,这里就在对method的注解进行判断了(现在你就可以猜想一下这个Converter<ResponseBody, ?>的具体功能),通过判断的结果返回的可能有三种实例,都是单例的看一下这三种实例,内部都实现那些方法:

    static final class RequestBodyConverter implements Converter<RequestBody, RequestBody> {
        static final RequestBodyConverter INSTANCE = new RequestBodyConverter();
    
        @Override public RequestBody convert(RequestBody value) throws IOException {
          return value;
        }
      }
    
      static final class StreamingResponseBodyConverter
          implements Converter<ResponseBody, ResponseBody> {
        static final StreamingResponseBodyConverter INSTANCE = new StreamingResponseBodyConverter();
    
        @Override public ResponseBody convert(ResponseBody value) throws IOException {
          return value;
        }
      }
    
      static final class BufferingResponseBodyConverter
          implements Converter<ResponseBody, ResponseBody> {
        static final BufferingResponseBodyConverter INSTANCE = new BufferingResponseBodyConverter();
    
        @Override public ResponseBody convert(ResponseBody value) throws IOException {
          try {
            // Buffer the entire body to avoid future I/O.
            return Utils.buffer(value);
          } finally {
            value.close();
          }
        }
      }
    

    哦哦 看到这里是不是有点眼熟啊

    @Override public ResponseBody convert(ResponseBody value)这个方法又是对传入的参数做了一个转换!看一下接口Converter的定义:

    public interface Converter<F, T> {
      T convert(F value) throws IOException;
      ...
    }
    

    将F转为T,不过三个具体实现都是Converter<ResponseBody, ResponseBody>,所以这里有些看不懂呢,不过没关系,这个参数先到这里为止吧!不影响继续探索。

    requestFactory:

    在MethodHandler里requestFactory是像这样创建的

     RequestFactory requestFactory = RequestFactoryParser.parse(method, responseType, retrofit);
    

    静态方法RequestFactoryParser.parse(),那么就去看看这个类里具体是怎么创建requestFactory的吧:

    static RequestFactory parse(Method method, Type responseType, Retrofit retrofit) {
        RequestFactoryParser parser = new RequestFactoryParser(method);
    
        Annotation[] methodAnnotations = method.getAnnotations();
        parser.parseMethodAnnotations(responseType, methodAnnotations);
        parser.parseParameters(retrofit, methodAnnotations);
    
        return parser.toRequestFactory(retrofit.baseUrl());
      }
    

    首先是初始化自己,并在自己的构造方法里把传入的method全局化。在看到Annotation[]注解列表了没有?说明RequestFactoryParser这个类先对methodAnnotations进行解析,然后将解析的结果用在在toRequestFactory()方法对RequestFactory里做了对初始化:

    private RequestFactory toRequestFactory(BaseUrl baseUrl) {
        return new RequestFactory(httpMethod, baseUrl, relativeUrl, headers, contentType, hasBody,
            isFormEncoded, isMultipart, requestActions);
      }
    

    那么这个类其实最关键的作用就是解析method的注解了。有两个重要的方法也是它在静态方法里调用的那两方法:

        //对method方法注解类型做判断调用解析方法,将注解名称赋值相关全局变量,
        //如果注解的value不为空也要赋值给付给全局变量,这些全局变量就是用来创建RequestFactory的。
        parser.parseMethodAnnotations(responseType, methodAnnotations);
        //对method参数的注解做解析,将注解名称赋值相关全局变量,这些全局变量也是用来创建RequestFactory的。
        parser.parseParameters(retrofit, methodAnnotations);
    

    这里具体是怎么解析的可以看一下源码,代码太长了就不贴了,里面涉及到了很多注解类型的判断,想了解具体的实现,看一下这个RequestFactoryParser类里面的具体实现,代码总长度也很正常500多行。就看这两个重要方法就可以了。

    好了拿到所有的注解类型,以及注解的value(一般是relativeUrl,和baseUrl一起用来拼接请求链接的),就可以创建RequestFactory了。

    RequestFactory

    RequestFactory,从名字就可以看出,是用来创建Request的,它在RequestFactoryParser里拿到的所有参数就是用来创建Request的,这个工厂类里只有一个create方法:
    核心实现就是:

     RequestBuilder requestBuilder =
            new RequestBuilder(method, baseUrl.url(), relativeUrl, headers, contentType, hasBody,
                isFormEncoded, isMultipart);
        ...
        return requestBuilder.build();
    

    里面也是build模式创建的request,中间省略的代码,其作用我也不确定,所以暂时不写它的作用了,以后确定了再补上。

    当然RequestBuilder里面为了请求体Request的构建也做了大量大操作,最终创建了Request,详细的内容只有再去撸源码了,这里我也不能说的很清楚了。

    那么到这里就找到了创建OkHttpCall<>所用到的所有参数了创建也在这里结束。接下来看看OkHttpCall<>用这些参数能做些什么事情。

    五、OkHttpCall<>网络请求的真实面目

    还记得第三章最后写到的例子吗:

        MyApi api = retrofit.create(MyApi.class);
        Response<User> user = api.getUser().execute();
    

    这里的MyApi api就是被这个生成的代理对象赋值,代理对象和被代理对象拥有同名方法getUser(),这里的这个getUser()方法返回值就是MethodHandler.invok()的返回值OkHttpCall<>了。execute()就是OkHttpCall<>里面的网络请求的方法。

    retrofit的最后一哆嗦就是调用用我们创建的OkHttpCall<>的execute()完成网络请求。execute()方法内容就比较长涉及到的也跟构建OkHttpCall<>传入的4个参数有关。这些参数在上一章中有详细的讲解,这里就不多说了。还是贴一下execute()的部分代码看看

    @Override public Response<T> execute() throws IOException {
        okhttp3.Call call;
    
      ...
          call = rawCall;
          if (call == null) {
            try {
              call = rawCall = createRawCall();
            } catch (IOException | RuntimeException e) {
              creationFailure = e;
              throw e;
            }
          }
        }
    
        if (canceled) {
          call.cancel();
        }
    
        return parseResponse(call.execute());
      }
    

    这里创建的okhttp3.Call 是通过createRawCall()方法创建的,先不管后面的代码,直接看看createRawCall()方法是怎么写的:

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

    callFactory通过几次的传递,终于开始发挥它的作用了,一开始就知道他是一个OkHttpClient,在这里就是调用它的newCall()用来创建一个Call,这个方法需要一个Request,在上一章尾门已经知道了Request是怎么来的了。那么直接看newCall方法的内部:

    return new RealCall(this, request);
    

    返回的是RealCall,它实现了Call的接口,那么OkHttpCall的execute()方法最后返回值的时候就是解析的这个RellCall 的execute()方法的返回值。这知道怎么用OkHttp得是不是很眼熟?看一下OkHttp的使用示例代码:

    String url = "https://www.baidu.com/";
    OkHttpClient okHttpClient = new OkHttpClient();
    Request request = new Request.Builder()
        .url(url)
        .build();
    Call call = okHttpClient.newCall(request);
    try {
        Response response = call.execute();
        System.out.println(response.body().string());
    } catch (IOException e) {
        e.printStackTrace();
    }
    
    

    六、总结

    从这段请求示例来看,最后总结Retrofit所做的事情就是:

    1. create生成一个我们自己写好的接口(这个接口的方法、方法里的参数都要有Retrofit对应的注解做标记)的动态代理对象。
    2. 在创建动态代理对象的过程中要对被代理对象(我们写好的接口)里的方法作合法化处理。
    3. 方法的合理化确切的说是在调用代理对象的方法(与我们写的接口里的方法同名)时开始的,也就是那个创建MethodHandler.create()开始的。
    4. 最开始是初始化CallAdapter.
    5. 然后初始化requestFactory,在这里就解析了所有的注解拼接了字段。为创建OkHttp.Requst做准备。
    6. 在合法化处理第二个步骤就是MethodHandler的invoke()方法,通过CallAdapter的adpt方法创建了OkHttpCall<>。
    7. 接下来发生的所有事情就是在这个OkHttpCall<>里了。它用到了一直没有用过的CallFactory也就是OkHttpClient创建了RealCall对象,创建这个对象时用到了requestFactory.creat()方法(这里把也是一直没有用到的args,也就是用于网络请求的参数传了过去),返回的Request对象。至此OkHttpClient已经配置全部完成!
     Retrofit retrofit = new Retrofit.Builder()
         .baseUrl("http://api.example.com")
         .addConverterFactory(GsonConverterFactory.create())
         .build();
     MyApi api = retrofit.create(MyApi.class);
     Response<User> user = api.getUser().execute();
    

    上面这段代码中getUser(),就是那个代理对象的方法。法返回的就是OkHttpCall<>对象,同时OkHttpCall<>已经将OkHttpClient(请求的方法、参数)配置好了。最后就是调用execute()方法,其实际就是调用了OkHttpClient创建的RealCall对象的execute()方法。然后再用parseResponse()将okhttp3.Response转换成retrofit2.ResPonse作为最后网络请求的结果返回。


    那具体的网路请求的实现(RealCall对象的execute()方法)就是OkHttpClient的事情了。具体的实现就要看OkHttp的源码了,这个就留在下次解析吧。

    结束!

    相关文章

      网友评论

        本文标题:retrofit源码解析

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