Android Retrofit2(二)源码解读

作者: 程序员三千_ | 来源:发表于2020-04-22 14:24 被阅读0次

    根据retrofit的使用,我们将源码分析分为4个阶段来分析:

    步骤1、如何获取retrofit对象

     val retrofit = Retrofit.Builder()
                //Retrofit2的baseUrl 必须以 /(斜杆)结束,抛出一个IllegalArgumentException
               .baseUrl("https://www.wanandroid.com/")
               .addConverterFactory(GsonConverterFactory.create())
               .build()
    

    步骤2、怎么根据自己定义的接口获取接口的代理实例的

    WanAndroidApi wanAndroidApi =retrofit.createWanAndroidApi.class);//代理实例
    

    步骤3、怎么根据代理实例获取Call对象的

    Call<ProjectBean> call = wanAndroidApi.getProject();//获取具体的某个业务 //同步请求
    

    步骤4、怎么根据Call对象完成真正的网络请求的

    call.enqueue或者call.execute();
    

    我们先大体过下流程,了解下整个骨架

    //业务接口
    @GET("project/tree/json")
     fun getProject(): Call<ProjectBean>
    
    image.png

    我们通过断点调试直接进入Rtrofit.builder()方法
    =>MainActivity#Retrofit.Builder().build()
    =>Rtrofit.builder()

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

    一开始先通过okhttp3.Call.Factory获取到OkHttpClient对象callFactory,
    (OkHttpClient属于okhttp3),

    =>Rtrofit#platform.defaultCallbackExecutor();

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

    我们看到platform.defaultCallbackExecutor()是返回一个MainThreadExecutor对象的,在MainThreadExecutor实现了Executor接口重写了execute方法,并在内部创建了一个主线程的handler,在execute方法里调用handler的post方法去发送消息,这段代码就解释了,我们在使用retrofit的时候是在子线程的,但返回结果可以在UI主线程的原因。

    后面一部分代码就是把之前传进来的GsonConverterFactory等添加到converterFactories里,然后返回一个Retrofit对象,步骤一很简单,分析完了,接下去看步骤2,我们往下走

    =>val wanAndroidApi = retrofit.create(WanAndroidApi::class.java)
    => #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);
             }
           });
     }
    

    这代段代码很熟悉,就是根据动态代理,返回一个代理对象,然后我们在执行代理对象的相应方法的时候(wanAndroidApi.getProject()),就会进入到invoke方法里,最后return进入loadServiceMethod方法。
    我们先进入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);
         }
       }
    

    在loadServiceMethod一开始先去serviceMethodCache里去取,如果取不到,
    再调用parseAnnotations方法,我们再点击parseAnnotations方法看看

    abstract class ServiceMethod<T> {
     static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
       RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);
    
       Type returnType = method.getGenericReturnType();
       if (Utils.hasUnresolvableType(returnType)) {
         throw methodError(method,
             "Method return type must not include a type variable or wildcard: %s", returnType);
       }
       if (returnType == void.class) {
         throw methodError(method, "Service methods cannot return void.");
       }
    
       return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
     }
    
     abstract @Nullable T invoke(Object[] args);
    }
    
    

    我们发现它是一个抽象类,并且存在一个静态方法parseAnnotations和一个抽象方法invoke,在静态方法parseAnnotations的方法体里, 其实就干了一件事,就是把我们接口注解的信息全部解析出来

    
    @GET("project/tree/json")
      fun getProject(): Call<ProjectBean>
    

    所以综上,loadServiceMethod方法就是通过反射把我们注解的信息全部解析出来保存在一个serviceMethodCache集合里

    
     private final Map<Method, ServiceMethod<?>> serviceMethodCache = new ConcurrentHashMap<>();
    
    

    我们可以简单的理解为,我们每一个注解的方法就相当于一个ServiceMethod对象

    getProject <==>ServiceMethod
    因为反射是很耗费性能的,所以前面新建了个缓存集合serviceMethodCache。

    我们再进入parseAnnotations方法看看具体是怎么解析的

     static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
        RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);
    
        Type returnType = method.getGenericReturnType();
        if (Utils.hasUnresolvableType(returnType)) {
          throw methodError(method,
              "Method return type must not include a type variable or wildcard: %s", returnType);
        }
        if (returnType == void.class) {
          throw methodError(method, "Service methods cannot return void.");
        }
    
        return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
      }
    
    

    一开始调用了RequestFactory.parseAnnotations(retrofit, method),
    这里面就是解析一些请求参数的并把它封装到RequestFactory里,
    我们直接进入RequestFactory#Builder方法看看

    final class RequestFactory# {
      static RequestFactory parseAnnotations(Retrofit retrofit, Method method) {
        return new Builder(retrofit, method).build();
      }
    
     Builder(Retrofit retrofit, Method method) {
          this.retrofit = retrofit;
          this.method = method;
          this.methodAnnotations = method.getAnnotations();
          this.parameterTypes = method.getGenericParameterTypes();
          this.parameterAnnotationsArray = method.getParameterAnnotations();
        }
    

    和大多数框架一样这里也通过建造者模式做的,我们来看看Builder里的几个参数的含义,method里其实就保存的我们自己定义的接口方法getProject()


    image.png

    methodAnnotations里通过method.getAnnotations()获取我们方法getProject()上的方法类的注解


    image.png
    parameterTypes里通过method.getGenericParameterTypes()获取我们方法的范型信息
    parameterAnnotationsArray里通过method.getParameterAnnotations获取我们方法上的参数类的注解

    获取完这些信息,我们进入RequestFactory的build方法来进行真正的构建

    RequestFactory build() {
          for (Annotation annotation : methodAnnotations) {
            parseMethodAnnotation(annotation);
          }
    
          if (httpMethod == null) {
            throw methodError(method, "HTTP method annotation is required (e.g., @GET, @POST, etc.).");
          }
    
          if (!hasBody) {
            if (isMultipart) {
              throw methodError(method,
                  "Multipart can only be specified on HTTP methods with request body (e.g., @POST).");
            }
            if (isFormEncoded) {
              throw methodError(method, "FormUrlEncoded can only be specified on HTTP methods with "
                  + "request body (e.g., @POST).");
            }
          }
    
          int parameterCount = parameterAnnotationsArray.length;
          parameterHandlers = new ParameterHandler<?>[parameterCount];
          for (int p = 0, lastParameter = parameterCount - 1; p < parameterCount; p++) {
            parameterHandlers[p] =
                parseParameter(p, parameterTypes[p], parameterAnnotationsArray[p], p == lastParameter);
          }
    
          if (relativeUrl == null && !gotUrl) {
            throw methodError(method, "Missing either @%s URL or @Url parameter.", httpMethod);
          }
          if (!isFormEncoded && !isMultipart && !hasBody && gotBody) {
            throw methodError(method, "Non-body HTTP method cannot contain @Body.");
          }
          if (isFormEncoded && !gotField) {
            throw methodError(method, "Form-encoded method must contain at least one @Field.");
          }
          if (isMultipart && !gotPart) {
            throw methodError(method, "Multipart method must contain at least one @Part.");
          }
    
          return new RequestFactory(this);
        }
    

    一开始就是循环我们之前的methodAnnotations,来获取我们方法类的注解,我们进入parseMethodAnnotation方法,

        private void parseMethodAnnotation(Annotation annotation) {
          if (annotation instanceof DELETE) {
            parseHttpMethodAndPath("DELETE", ((DELETE) annotation).value(), false);
          } else if (annotation instanceof GET) {
            parseHttpMethodAndPath("GET", ((GET) annotation).value(), false);
          } else if (annotation instanceof HEAD) {
            parseHttpMethodAndPath("HEAD", ((HEAD) annotation).value(), false);
          } else if (annotation instanceof PATCH) {
            parseHttpMethodAndPath("PATCH", ((PATCH) annotation).value(), true);
          } else if (annotation instanceof POST) {
            parseHttpMethodAndPath("POST", ((POST) annotation).value(), true);
          } else if (annotation instanceof PUT) {
            parseHttpMethodAndPath("PUT", ((PUT) annotation).value(), true);
          } else if (annotation instanceof OPTIONS) {
            parseHttpMethodAndPath("OPTIONS", ((OPTIONS) annotation).value(), false);
          } else if (annotation instanceof HTTP) {
            HTTP http = (HTTP) annotation;
            parseHttpMethodAndPath(http.method(), http.path(), http.hasBody());
          } else if (annotation instanceof retrofit2.http.Headers) {
            String[] headersToParse = ((retrofit2.http.Headers) annotation).value();
            if (headersToParse.length == 0) {
              throw methodError(method, "@Headers annotation is empty.");
            }
            headers = parseHeaders(headersToParse);
          } else if (annotation instanceof Multipart) {
            if (isFormEncoded) {
              throw methodError(method, "Only one encoding annotation is allowed.");
            }
            isMultipart = true;
          } else if (annotation instanceof FormUrlEncoded) {
            if (isMultipart) {
              throw methodError(method, "Only one encoding annotation is allowed.");
            }
            isFormEncoded = true;
          }
        }
    

    因为我们是GET注解,所有我们传入GET进入parseHttpMethodAndPath方法


    image.png

    通过断点看到,最后返回了方法上真正的"project/tree/json"赋值给relativeUrl,relativeUrlParamNames参数其实是保存url带参数的那种的,例如

        @GET("project/{id}/list")
    

    里面是通过正则表达式的方式获取{id},我们现在是没有。
    解析完方法上所有的信息后,我们接着往下看

      int parameterCount = parameterAnnotationsArray.length;
          parameterHandlers = new ParameterHandler<?>[parameterCount];
          for (int p = 0, lastParameter = parameterCount - 1; p < parameterCount; p++) {
            parameterHandlers[p] =
                parseParameter(p, parameterTypes[p], parameterAnnotationsArray[p], p == lastParameter);
          }
    

    这里就是真正的来解析的我方法里的参数类的注解了,我们进入parseParameter方法

    
     private @Nullable ParameterHandler<?> parseParameter(
            int p, Type parameterType, @Nullable Annotation[] annotations, boolean allowContinuation) {
          ParameterHandler<?> result = null;
          if (annotations != null) {
            for (Annotation annotation : annotations) {
              ParameterHandler<?> annotationAction =
                  parseParameterAnnotation(p, parameterType, annotations, annotation);
    
              if (annotationAction == null) {
                continue;
              }
    

    我们再进入parseParameterAnnotation看看具体的解析

     @Nullable
        private ParameterHandler<?> parseParameterAnnotation(
            int p, Type type, Annotation[] annotations, Annotation annotation) {
          if (annotation instanceof Url) {
           
          } else if (annotation instanceof Query) {
         
            } else if (rawParameterType.isArray()) {
            
          } else if (annotation instanceof QueryName) {
        
            } else if (rawParameterType.isArray()) {
             
          } else if (annotation instanceof QueryMap) {
           
          } else if (annotation instanceof Header) {
    
          } else if (rawParameterType.isArray()) {
          
    
          } else if (annotation instanceof HeaderMap) {
          
          } else if (annotation instanceof Field) {
           
          } else if (annotation instanceof FieldMap) {
           ........
        }
    
    

    因为里面的代码太多了,我就拿了一些主要代码,里面其实就是判断你的参数类注解是哪个,然后对应的去解析,也没什么可讲的。
    到这里已经把我们的所有的请求方法和参数都解析完成,并在封装在RequestFactory请求工厂里了。


    image.png

    我们接着ServiceMethod类看

    
    abstract class ServiceMethod<T> {
      static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
        RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);
    
        Type returnType = method.getGenericReturnType();
        if (Utils.hasUnresolvableType(returnType)) {
          throw methodError(method,
              "Method return type must not include a type variable or wildcard: %s", returnType);
        }
        if (returnType == void.class) {
          throw methodError(method, "Service methods cannot return void.");
        }
    
        return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
      }
    
      abstract @Nullable T invoke(Object[] args);
    }
    
    image.png

    看上图,现在除了我红线圈出来的地方,其他都已经解析完毕封装在RequestFactory里了,接下来我们就来看看具体剩余的部分是怎么解析的。

    比如我们自己封装的RxJava+retrofit+OkHttp的网络请求框架的时候,可能是这样的


    image.png
    
     retrofit = new Retrofit
                    .Builder()
                    .client(getOkHttpClient())
                    .baseUrl(baseUrl)
                    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                    .addConverterFactory(GsonConverterFactory.create()).build();
    

    创建了一个RxJava2CallAdapterFactory的CallAdapterFactory,在单独使用retrofit的时候是不传的,还有一个,我们如果自己封装了一个Bean类的话,也会传进一个GsonConverterFactory的ConverterFactory转换器工厂,

    那在Retrofit里是怎么解析的呢?根据断点,我们进入到HttpServiceMethod类,
    我们发现HttpServiceMethod类是继承自ServiceMethod类的,之前我们解析请求方法和请求参数就是在ServiceMethod类里的,我们直接看到HttpServiceMethod的静态方法parseAnnotations

       */
      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) {
          return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
        } else if (continuationWantsResponse) {
          //noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
          return (HttpServiceMethod<ResponseT, ReturnT>) new SuspendForResponse<>(requestFactory,
              callFactory, responseConverter, (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter);
        } else {
          //noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
          return (HttpServiceMethod<ResponseT, ReturnT>) new SuspendForBody<>(requestFactory,
              callFactory, responseConverter, (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter,
              continuationBodyNullable);
        }
      }
    

    我们直接根据断点走到

    
    CallAdapter<ResponseT, ReturnT> callAdapter =
            createCallAdapter(retrofit, method, adapterType, annotations);
    

    我们看到接口CallAdapter的实现类,发现适配器确实和我们前面分析的一样,有很多种,


    image.png

    这里就用到了适配器模式,那到底是怎么实现的呢?我们再点进createCallAdapter看看他怎么创建的

    private static <ResponseT, ReturnT> CallAdapter<ResponseT, ReturnT> createCallAdapter(
          Retrofit retrofit, Method method, Type returnType, Annotation[] annotations) {
        try {
          //noinspection unchecked
          return (CallAdapter<ResponseT, ReturnT>) retrofit.callAdapter(returnType, annotations);
        } catch (RuntimeException e) { // Wide exception range because factories are user code.
          throw methodError(method, e, "Unable to create call adapter for %s", returnType);
        }
      }
    
    
     public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {
        return nextCallAdapter(null, returnType, annotations);
      }
    
     public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType,
          Annotation[] annotations) {
        Objects.requireNonNull(returnType, "returnType == null");
        Objects.requireNonNull(annotations, "annotations == null");
    
        int start = callAdapterFactories.indexOf(skipPast) + 1;
        for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
          CallAdapter<?, ?> adapter = callAdapterFactories.get(i).get(returnType, annotations, this);
          if (adapter != null) {
            return adapter;
          }
        }
    

    我们看到 CallAdapter<?, ?> adapter = callAdapterFactories.get(i).get(returnType, annotations, this);,最后是根据我们传进去的returnType,annotations和retrofit对象在适配器工厂里获取的adapter适配器。


    returnType
    annotations retrofit
    image.png

    通过断点我们可以看到最后返回的适配器就是retrofit里的默认适配器
    DefaultCallAdapterFactory,适配器里面的ResponseT就是我们自己的实体类ProjectBean,接着往下看

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

    这句话和上面分析的流程差不多就是返回我们前面添加的转化器。Gson转化器
    GsonConverterFactory,然后再获取okhttp3.Call.Factory的callFactory对象,因为我们是默认的适配器,根据断点我们再进入 return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);将前面获取的请求参数工厂requestFactory,OkHttp3的callFactory对象,responseConverter解析转化器,和默认的DefaultCallAdapterFactory,new出一个CallAdapted,最后return回去,所以我们再一步步返回到前面的代码

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

    loadServiceMethod(method)这一部分我们都分析完了,根据动态代理的原理,接下来我们进入loadServiceMethod(method)的invoke方法的分析,看看是怎么执行代理对象的具体方法的。直接跟着断点,

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

    进入invoke方法一开始新建一个OkHttpCall,ResponseT就是我们的实体类ProjectBean,然后再根据OkHttpCall和我们传进来的参数args,返回一个adapt,我们具体看看adapt怎么实现的。

     @Override protected ReturnT adapt(Call<ResponseT> call, Object[] args) {
          return callAdapter.adapt(call);
        }
    
    

    就是根据CallAdapter接口返回具体的接口实现类,这里就是DefaultCallAdapterFactory,所以这里的adapt方法就是调用DefaultCallAdapterFactory里的adapt方法,我们进去看看

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

    因为一开始executor肯定是等于null的,所以进入new ExecutorCallbackCall<>(executor, call);,新建一个ExecutorCallbackCall,

    
      ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
          this.callbackExecutor = callbackExecutor;
          this.delegate = delegate;
        }
    

    这里就会给DefaultCallAdapterFactory里的callbackExecutor和delegate赋值,最后DefaultCallAdapterFactory这个适配器里所有的数据都初始化好了,再一层层返回回去,


    image.png

    到这里我们步骤3的Call对象对象就获取到了。如下图,我们整个业务接口的解析都完成了

      @GET("project/tree/json")
        fun getProject(): Call<ProjectBean>
    

    Call对象也获取到了,就是DefaultCallAdapterFactory里的ExecutorCallbackCall,通过断点,我们看到ExecutorCallbackCall里是包含了我们用于网络请求的OkHttpCall的,至此,文章一开始的前面3个步骤都已经完成了。

    步骤2和步骤3相对步骤1来说比较复杂,我们再来总结下

    • 一、通过Proxy.newProxyInstance返回一个业务接口的代理对象
    • 二、调用InvocationHandler接口的invoke方法
    • 三、在invoke方法里会调用到loadServiceMethod,在loadServiceMethod里会调用到ServiceMethod的parseAnnotations方法,在parseAnnotations方法里做了什么事情,具体可以分为两步:
      1、在ServiceMethod的parseAnnotations里,把我们的所有的请求方法和参数都解析完成,并在封装在RequestFactory。
      2、在HttpServiceMethod的parseAnnotations里(HttpServiceMethod继承自ServiceMethod):
      2.1、确定了CallAdapter是默认的DefaultCallAdapterFactory
      2.2、确定了我们的转化器responseConverter,我们这里用了GsonConverterFactory转化器。
      2.3、将CallAdapter、responseConverter、RequestFactory、okhttp3.Call.Factory 传入新建CallAdapted对象
    • 四、调用loadServiceMethod.invoke方法通过CallAdapted的adapt真正调用到DefaultCallAdapterFactory的adapt方法最终确定了ExecutorCallbackCall,
      ExecutorCallbackCall里就包含了真正执行网络请求的OkHttpCall和用于返回网络请求结果的callback回调接口Executor 。

    接下来就是分析步骤四:怎么根据Call对象完成真正的网络请求了。
    我们看看真正执行的projectCall.enqueue方法

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

    我们看到就是调用了前面获取的ExecutorCallbackCall里面的 delegate.enqueue,这里使用的是静态代理的模式,delegate实际上就是我们前面一步创建的OkHttpCall,


    image.png
    
    @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
            }
          }
        });
      }
    

    这里就是真正请求网络的地方,在createRawCall里就是创建OkHttp网络请求所需要的newCall的地方

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

    我们在看看我们的Gson转化器是在哪里用到了,看到解析成功的onResponse方法里的response = parseResponse(rawResponse);,

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

    T body = responseConverter.convert(catchingBody);这一句就真正的调用转化器把OkHttp请求返回的结果转化成实体bean,通过callback真正返回回去了。至此整个retrofit的源码就分析完成了。

    完整流程

    • 一、通过Proxy.newProxyInstance返回一个业务接口的代理对象
    • 二、调用InvocationHandler接口的invoke方法
    • 三、在invoke方法里会调用到loadServiceMethod,在loadServiceMethod里会调用到ServiceMethod的parseAnnotations方法,在parseAnnotations方法里做了什么事情,具体可以分为两步:
      1、在ServiceMethod的parseAnnotations里,把我们的所有的请求方法和参数都解析完成,并在封装在RequestFactory。
      2、在HttpServiceMethod的parseAnnotations里(HttpServiceMethod继承自ServiceMethod):
      2.1、确定了CallAdapter是默认的DefaultCallAdapterFactory
      2.2、确定了我们的转化器responseConverter,我们这里用了GsonConverterFactory转化器。
      2.3、将CallAdapter、responseConverter、RequestFactory、okhttp3.Call.Factory 传入新建CallAdapted对象
    • 四、调用loadServiceMethod.invoke方法通过CallAdapted的adapt真正调用到DefaultCallAdapterFactory的adapt方法最终确定了ExecutorCallbackCall,
      ExecutorCallbackCall里就包含了真正执行网络请求的OkHttpCall和用于返回网络请求结果的callback回调接口Executor 。
    • 五、调用ExecutorCallbackCall里的delegate.enqueue发起真正的网络请求,并在请求成功回调的地方调用转换器把返回结果转换成我们需要的实体bean。

    Retrofit中的设计模式

      1. 建造者模式
        Retrofit对象的创建、ServiceMethod对象创建都使用Build模式,将复杂对象的创建和表示分离,调用 者不需要知道复杂的创建过程,使用Build的相关方法进行配置创建对象。
      1. 动态代理模式
        通过动态代理的方式,当调用Retrofit的create()方法时,会进行动态代理监听。当执行具体的接口方法时,会回调InvocationHandler。通过反射解析method的标注及参数,生成ServiceMethod对象。
      1. 静态代理模式
        Android平台默认的适配器ExecutorCallbackCall,采用静态代理的模式。具体的实现delegate为 OkHttpCall。
      1. 工厂模式
        Converter及CallAdapter的创建都采用了工厂模式进行创建。
      1. 适配器模式
        CallAdapter的adapt采用了适配器模式,使得interface的返回对象可以动态扩展,增强了灵活性

    相关文章

      网友评论

        本文标题:Android Retrofit2(二)源码解读

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