Retrofit源码解析

Retrofit 源码分析


知识预热

JAVA泛型类型
typedescriptionexampleremark
ParameterizedType参数化类型,通常意义上的泛型类型类实例List,Map<K,V>
TypeVariable类型化变量 泛型变量T t,K k,V v
GenericArrayType泛型数组List[], T[],
WildcardType通配符类型List<? extends String>
Class字节码类型

JDK动态代理

动态代理AOP(面向切面编程)的重要组成部分。

JDK动态动态代理要求被代理对象必须实现接口,InvocationHandler的派生类通过聚合该接口的实例,在其invoke方法中,转发接口的调用。示例如下,我们需要在某个代理对象的方法前后打印输入。

​ 假设存在某一服务接口如下

public interface IServer {
    void sayHello();
}

​ 业务类实现了该接口

public class Engine implements IServer {
    @Override
    public void sayHello() {
        System.out.println("Hello,I am Agent");
    }
}

​ 现在通过动态代理在方法前后打印输出。先定义自定义InvocationHandler

class ICommonHandler implements InvocationHandler {
	// 这里持有了IServer接口的实例
    private IServer agent;
    public ICommonHandler(IServer agent){
        this.agent = agent;
    }

    @Override
    public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
        // 调用前,修饰方法
        System.out.println("before function invoke");
        // 将调用准发给被代理对象
        Object result = method.invoke(agent, objects);
        // 调用前后修饰方法
        System.out.println("after function invoke");
        return result;
    }
}

​ 最后,通过Proxy.newProxyInstanceAPI获取代理后的对象。

    public static void main(String[] args) {
        try {
            // 被代理对象
            Engine agent = new Engine();
            // InvocationHandler 
            ICommonHandler invocationHandler  = new ICommonHandler(agent);
            // 获取动态代理后的对象
            IServer proxy = (IServer) Proxy.newProxyInstance(agent.getClass().getClassLoader(), agent.getClass().getInterfaces(), invocationHandler);
			// 通过代理对象调用相应的api
            proxy.sayHello();

        }catch(Exception exception){
            exception.printStackTrace();
        }
    }
JAVA反射相关
  • Method.getAnnotations:获取方法上的注解
  • Method.getGenericParameterTypes:获取方法参数类型
  • Method.getParameterAnnotations:获取方法参数注解
// 为了理解上述API,举例如下

// 自定义一个注解
@Retention(AnnotationRetention.RUNTIME)
annotation class JSON{
    
}

// 假设有如下接口类
interface GitHubService {
    @GET("users/{user}/repos")
    @HEAD(value = "contentType:application/json")
    fun listRepos(@Path("user")user:String,@JSON @Query("sign")sign:String): Call<List<Repo>>
}

// 测试类
public class Reflex {
    public static void main(String[] args) {

        try {
            Class<GitHubService> clazz = GitHubService.class;
            Method[] methods = clazz.getMethods();
            for(Method method:methods){
                method.setAccessible(true);
                System.out.println("method:"+method.getName()+"*************************");
                Annotation[] annotations = method.getAnnotations();
                Type[] genericParameterTypes = method.getGenericParameterTypes();
                Annotation[][] parameterAnnotations = method.getParameterAnnotations();

                for(Annotation annotation:annotations){
                    System.out.println("annotation:"+annotation.toString());
                }
                System.out.println("----------------------------------------");

                for(Type type:genericParameterTypes){
                    System.out.println("types:"+type.getTypeName());
                }
                System.out.println("----------------------------------------");

                for(Annotation[] a1:parameterAnnotations){
                    for(Annotation a:a1){
                            System.out.println("parameterAnnotation:"+a.toString());
                    }
                    System.out.println("##########################################");
                }

                System.out.println("----------------------------------------");

                System.out.println("method:"+method.getName()+"*************************");
            }
        }catch(Exception exception){
            exception.printStackTrace();
        }
    }
}

​ 打印如下

method:listRepos*************************
# getAnnotations
annotation:@retrofit2.http.GET(value=users/{user}/repos)
annotation:@retrofit2.http.HEAD(value=contentType:application/json)
----------------------------------------
# getGenericParameterTypes
types:java.lang.String
types:java.lang.String
----------------------------------------
# getParameterAnnotations
parameterAnnotation:@retrofit2.http.Path(encoded=false, value=user)
##########################################
parameterAnnotation:@api.JSON()
parameterAnnotation:@retrofit2.http.Query(encoded=false, value=sign)
##########################################
----------------------------------------
method:listRepos*************************

Retrofit使用

​ 在modulebuild.gradle.kts文件中添加如下依赖

dependencies {
    implementation("com.squareup.retrofit2:retrofit:2.9.0")
}

​ 创建API接口

public interface GitHubService {

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

}

​ 通过Retrofit实例生成实现API接口的实例对象

        // 获取Retrofit实例
		Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("https://api.github.com/")
                .build();

        GitHubService service = retrofit.create(GitHubService.class);

​ 通过该对象可以实现真实的HTTP访问

Call<List<Repo>> repos = service.listRepos("alibaba");

源码分析

​ 在Retrofit的使用过程中,Retrofit类通过构建者模式生成了一个Retrofit的实例,该实例通过create方法生成实现API接口的对象。create方法返回一个实现API接口的对象,其源码如下:

 @SuppressWarnings("unchecked") // Single-interface proxy creation guarded by parameter safety.
    public <T> T create(final Class<T> service) {
        // 验证API接口的有效性
        validateServiceInterface(service);
        // 这里直接使用了java的动态代理
        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);
                                }
                                args = args != null ? args : emptyArgs;
                                return platform.isDefaultMethod(method)
                                        ? platform.invokeDefaultMethod(method, service, proxy, args)
                                        : loadServiceMethod(method).invoke(args);
                            }
                        });
    }

create方法的核心是通过动态代理技术,返回一个代理实例.在返回代理对象之前,必须对传入的API接口进行校验.

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) {
            // 平台类型工具类
            Platform platform = Platform.get();
            for (Method method : service.getDeclaredMethods()) {
                // 加载所有的非默认方法与非静态方法(jdk1.8在接口了增加了default方法的定义)
                if (!platform.isDefaultMethod(method) && !Modifier.isStatic(method.getModifiers())) {
                    loadServiceMethod(method);
                }
            }
        }
    }

​ 接口验证的主要目的在于确定API接口是纯粹的接口,首先从语义上必须是一个Interface,其次,必须是一个非泛型接口,最后,通过loadServiceMehod方法加载接口中所有的非默认方法与非静态方法.

    ServiceMethod<?> loadServiceMethod(Method method) {
        // serviceMethodCache 是一个类型安全的容器,通过缓存,保证方法的解析只进行一次
        ServiceMethod<?> result = serviceMethodCache.get(method);
        if (result != null) return result;

        // 同步代码
        synchronized (serviceMethodCache) {
            result = serviceMethodCache.get(method);
            if (result == null) {
                // 解析方法,并返回ServiceMehod对象
                result = ServiceMethod.parseAnnotations(this, method);
                // 将解析结果存放在缓存中,避免下次再次解析方法
                serviceMethodCache.put(method, result);
            }
        }
        return result;
    }

loadServiceMehod方法通过ServiceMethod.parseannotations的静态方法解析接口中的方法,并返回一个ServiceMethod对象,当用户调用接口中的方法时,其实最终调用的是serviceMethod.invoke函数.需要说明的一点是,用户存在多次调用接口中的同一方法,为了避免每次调用都解析方法一次,loadServiceMehod方法在解析方法过程中使用了内存缓存,即通过ConcurrentHashMap这样一个线程安全的容器去缓存每次解析的结果.

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.");
    }
	
      // 这里主要是加入了对kotlin协程的支持,继续解析方法返回值
    return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
  }

    // 外部调用API服务最终通过该方法
  abstract @Nullable T invoke(Object[] args);
}
方法注解的解析

parseAnnotations()方法主要用于解析方法注解,并返回RequestFactory对象.该方法的主要逻辑如上注解所有.需要说明的是最新版本的Retrofit已经支持Kotlin 协程,所以在最新的源码中,可以看见这部分的源码.

​ 个人感觉Retrofit在解析方法注解这部分做的非常优雅.parseAnnotations方法如下

final class RequestFactory {
  static RequestFactory parseAnnotations(Retrofit retrofit, Method method) {
    // RequestFactory 使用了构建者模式.
    return new Builder(retrofit, method).build();
  }
}

​ 他的构建者如下,在其构造方法参数中,methodAnnotations,parameterTypes,parameterAnnotationsArray这三个参数非常重要,因为后续的所有解析操作均围绕这三者,在构建者的build方法中,正式开启了解析操作.

Builder(Retrofit retrofit, Method method) {
      this.retrofit = retrofit;
      this.method = method;
      // 获取方法上的注解
      this.methodAnnotations = method.getAnnotations();
      // 获取方法参数类型
      this.parameterTypes = method.getGenericParameterTypes();
      // 获取方法参数上的注解,这是一个二维数组
      this.parameterAnnotationsArray = method.getParameterAnnotations();
    }

    RequestFactory build() {
      for (Annotation annotation : methodAnnotations) {
        // 解析方法注解  
        parseMethodAnnotation(annotation);
      }

      // 解析方法后验证相关参数
      // 如接口中必须表明HTTP的连接方式 GET,POST,PUT,PATCH,DELETE等
      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.");
      }
   
      // 返回RequestFactory对象  
      return new RequestFactory(this);
    }

​ 解析的过程比较简单

  1. 先解析方法参数

  2. 再解析方法

     ##### `解析方法上的注解`
    

​ 在上述的方法中,通过parseMethodAnnotation方法解析方法上的注解

// 解析方法注解
// 通过枚举不同的注解类型,可以判断如下信息
// 1.HTTP请求方法,delete,post,get,put,patch,options,delete
// 2.通过请求方式,确认是否存在请求体
// 3.通过请求方式,确认参数组织方式,请求体或者表单传参
// 4.通过注解中参数,可以确定HTTP的路径,相对于BaseUrl
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;
      }
    }

​ 上述的业务逻辑比较简单,通过方法注解可以了解如下的基本信息

  1. HTTP请求方法,delete,post,get,put,patch,options,delete

  2. 通过请求方式,确认是否存在请求体,只有post,put,patch方式的请求才可能携带请求体

  3. 通过@FormUrlEncodedMultipart注解确认是否通过表单传参

  4. 通过注解参数确认相对路径

  5. 通过HeadsHead注解确认请求头

解析方法参数

​ 当方法注解解析完成后,需要对部分解析结果做验证,验证的方向为请求体与表单传参两者不可同时存在.验证之后即可以开始解析方法参数.在源码中通过如下代码实现

    // parameterAnnotationsArray 为方法参数中的注解数组  
	int parameterCount = parameterAnnotationsArray.length;
      parameterHandlers = new ParameterHandler<?>[parameterCount];
      for (int p = 0, lastParameter = parameterCount - 1; p < parameterCount; p++) {
          // 每一个参数的解析结果都返回一个parameterHandler的结果
        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;
          }

          if (result != null) {
            throw parameterError(
                method, p, "Multiple Retrofit annotations found, only one allowed.");
          }

          result = annotationAction;
        }
      }

      // 适配kotlin协程  
      if (result == null) {
        // 确认是supend函数的依据为最后方法参数为Continuation类型(续体)  
        if (allowContinuation) {
          try {
            // 确认是kotlin suspend 函数  
            if (Utils.getRawType(parameterType) == Continuation.class) {
              isKotlinSuspendFunction = true;
              return null;
            }
          } catch (NoClassDefFoundError ignored) {
          }
        }
        throw parameterError(method, p, "No Retrofit annotation found.");
      }

      return result;
    }

​ 在上述方法中,parseParameterAnnotation为最终调用的解析方法参数的方法,该方法比较长,他会枚举所有的注解类型,针对不同类型使用不同解析策略,并返回统一的解析结果ParameterHandler,部分源码如下

    @Nullable
    private ParameterHandler<?> parseParameterAnnotation(
        int p, Type type, Annotation[] annotations, Annotation annotation) {
    	if (annotation instanceof Url) {
       	 	validateResolvableType(p, type);
        	// 
            //   参数验证.....
            //
            gotUrl = true;

        	if (type == HttpUrl.class
            	|| type == String.class
            	|| type == URI.class
           		|| (type instanceof Class && "android.net.Uri".equals(((Class<?>) type).getName()))) {
          		return new ParameterHandler.RelativeUrl(method, p);
        	} else {
         		 throw parameterError(
              	 method,
             	 p,
                 "@Url must be okhttp3.HttpUrl, String, java.net.URI, or android.net.Uri type.");
        	}
        }else if(annotation instanceof Path){
            validateResolvableType(p, type);
            // 
            //   参数验证.....
            //
            gotPath = true;

        	Path path = (Path) annotation;
        	String name = path.value();
        	validatePathName(p, name);

        	Converter<?, String> converter = retrofit.stringConverter(type, annotations);
        	return new ParameterHandler.Path<>(method, p, name, converter, path.encoded());
        }else if(annotation instanceof Query){
            // ....
        }
        //	...      
    }

​ 在上述方法中,针对不同的注解类型提供了不同的解析策略,解析的结果对象为ParameterHandler.

abstract class ParameterHandler<T> {
    
  abstract void apply(RequestBuilder builder, @Nullable T value) throws IOException;

  final ParameterHandler<Iterable<T>> iterable() {
    return new ParameterHandler<Iterable<T>>() {
      @Override
      void apply(RequestBuilder builder, @Nullable Iterable<T> values) throws IOException {
        if (values == null) return; // Skip null values.

        for (T value : values) {
          ParameterHandler.this.apply(builder, value);
        }
      }
    };
  }

  final ParameterHandler<Object> array() {
    return new ParameterHandler<Object>() {
      @Override
      void apply(RequestBuilder builder, @Nullable Object values) throws IOException {
        if (values == null) return; // Skip null values.

        for (int i = 0, size = Array.getLength(values); i < size; i++) {
          //noinspection unchecked
          ParameterHandler.this.apply(builder, (T) Array.get(values, i));
        }
      }
    };
  }
}

​ 这是一个抽象类,针对不同的注解,他提供了非常多的实现类

// Url注解的策略解析  
static final class RelativeUrl extends ParameterHandler<Object> {
    private final Method method;
    private final int p;

    RelativeUrl(Method method, int p) {
      this.method = method;
      this.p = p;
    }

    @Override
    void apply(RequestBuilder builder, @Nullable Object value) {
      if (value == null) {
        throw Utils.parameterError(method, p, "@Url parameter is null.");
      }
      builder.setRelativeUrl(value);
    }
  }
// Heads/Head注解的策略解析
  static final class Header<T> extends ParameterHandler<T> {
    private final String name;
    private final Converter<T, String> valueConverter;

    Header(String name, Converter<T, String> valueConverter) {
      this.name = Objects.requireNonNull(name, "name == null");
      this.valueConverter = valueConverter;
    }

    @Override
    void apply(RequestBuilder builder, @Nullable T value) throws IOException {
      if (value == null) return; // Skip null values.

      String headerValue = valueConverter.convert(value);
      if (headerValue == null) return; // Skip converted but null values.

      builder.addHeader(name, headerValue);
    }
  }

​ 最终,解析完方法参数后,所有的结果存储在RequestFactory.parameterHandlers属性中,最终在构建Request过程中会通过ParameterHandlerapply方法,逐步的完善Request,最终组成完整的Request.但此已是后话

函数返回值的解析

Retrofit已经支持Kotlin协程.在解析方法注解以及参数的过程中已经有体现.接下来,在解析方法返回值中也同样体现.在ServiceMethod类中,

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

HttpServiceMethod.parseAnnotations方法如下

abstract class HttpServiceMethod<ResponseT, ReturnT> extends ServiceMethod<ReturnT> {
  /**
   * Inspects the annotations on an interface method to construct a reusable service method that
   * speaks HTTP. This requires potentially-expensive reflection so it is best to build each service
   * method only once and reuse it.
   */
  static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
      Retrofit retrofit, Method method, RequestFactory requestFactory) {
    // 在上面的"RequestFactory.parseAnnotations"方法已经确定是否为susppend函数  
    boolean isKotlinSuspendFunction = requestFactory.isKotlinSuspendFunction;
    boolean continuationWantsResponse = false;
    boolean continuationBodyNullable = false;

    Annotation[] annotations = method.getAnnotations();
    Type adapterType;
      // susspend 函数类型
    if (isKotlinSuspendFunction) {
      Type[] parameterTypes = method.getGenericParameterTypes();
      Type responseType =
          Utils.getParameterLowerBound(
              0, (ParameterizedType) parameterTypes[parameterTypes.length - 1]);
        // Response<T>类型
      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确认CallAdapter类型 Call<T>
      adapterType = new Utils.ParameterizedTypeImpl(null, Call.class, responseType);
      annotations = SkipCallbackExecutorImpl.ensurePresent(annotations);
    } else {
      adapterType = method.getGenericReturnType();
    }

     // 获取CallAdapter
    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.");
    }
	// 获取Convert
    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);
    }
  }
}

HttpServiceMethod是一个抽象类,分别有三个静态内部的实现类CallAdapted,SuspendForResponse,SuspendForBody.在其parseAnnotations方法中,最终会返回上述三个实现类其中的一个.上述三个静态实现类的构造函数参数非常重要,举其中一简单的实现类

  static final class CallAdapted<ResponseT, ReturnT> extends HttpServiceMethod<ResponseT, ReturnT> {
    private final CallAdapter<ResponseT, ReturnT> callAdapter;

    CallAdapted(
        // 在ServiceMethod父类中完成构造完成
        RequestFactory requestFactory,
        okhttp3.Call.Factory callFactory,
        // 父类createCallAdapter方法
        Converter<ResponseBody, ResponseT> responseConverter,
        // 父类createResponseConverter方法
        CallAdapter<ResponseT, ReturnT> callAdapter) {
      super(requestFactory, callFactory, responseConverter);
      this.callAdapter = callAdapter;
    }

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

​ 在上述的构造函数中需要传入三个非常重要的对象RequestFactory,在对象的创建在ServiceMethod类中RequestFactory.parseAnnotations(retrofit, method).而ConvertCallAdapter均在其父类HttpServiceMethod中构建,具体如下

  static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
      Retrofit retrofit, Method method, RequestFactory requestFactory) {
      		// 省略其他业务代码
      
      	  //  calladapter
          CallAdapter<ResponseT, ReturnT> callAdapter =
        createCallAdapter(retrofit, method, adapterType, annotations);
      
      	 // Convert
          Converter<ResponseBody, ResponseT> responseConverter =
        createResponseConverter(retrofit, method, responseType);
      
  }

​ 追踪上述代码,最终发现,这两者的获取的对象都是retrofit持有的对象.

    Retrofit(
            okhttp3.Call.Factory callFactory,
            HttpUrl baseUrl,
            List<Converter.Factory> converterFactories,
            List<CallAdapter.Factory> callAdapterFactories,
            @Nullable Executor callbackExecutor,
            boolean validateEagerly) {
        this.callFactory = callFactory;
        this.baseUrl = baseUrl;
        // convert
        this.converterFactories = converterFactories; // Copy+unmodifiable at call site.
        // calladapter
        this.callAdapterFactories = callAdapterFactories; // Copy+unmodifiable at call site.
        this.callbackExecutor = callbackExecutor;
        this.validateEagerly = validateEagerly;
    }

Retrofit采用构建者模式,build方法方法中会预先加入一些内建的CallAdapterConvert.Factory实例

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.
            // 加入内建的CallAdapter 工厂
            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.
    		// 加入内建的Convert
            converterFactories.add(new BuiltInConverters());
            converterFactories.addAll(this.converterFactories);
            converterFactories.addAll(platform.defaultConverterFactories());

            return new Retrofit(
                    callFactory,
                    baseUrl,
                    unmodifiableList(converterFactories),
                    unmodifiableList(callAdapterFactories),
                    callbackExecutor,
                    validateEagerly);
        }

platform.defaultCallAdapterFactories(callbackExecutor)内建的CallAdapter

  List<? extends CallAdapter.Factory> defaultCallAdapterFactories(
      @Nullable Executor callbackExecutor) {
    DefaultCallAdapterFactory executorFactory = new DefaultCallAdapterFactory(callbackExecutor);
    return hasJava8Types
        ? asList(CompletableFutureCallAdapterFactory.INSTANCE, executorFactory)
        : singletonList(executorFactory);
  }

​ 这些内建的CallAdapter具体业务逻辑代码都比较简单.但需要知道的是,在Retrofit调用具体的API访问过程中最终都会调用到其中的adapter方法.具体的调用逻辑为

abstract class ServiceMethod<T> {
    abstract @Nullable T invoke(Object[] args);
}

​ 到其子类``

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

​ 查看HttpserviceMethod三个静态内部类,其adapter方法最终都会调用到callAdapter.adapter方法,也就是Retrofit内一些列的callAdapter.查看一下OkhttpCall的类,发现桥接okhttp的一些列代码.查看其中比较重要的方法

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

​ 这里通过requestFactory已经API传进来的参数,构建了一个Okhttp3.Call.这里可以看到requestFactory的最终归宿了.

  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 {
      // 这里使用了convert,将requestbody 转化为具体对象  
      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;
    }
  }

​ 需要注意的是parseResponse方法会在enqueue方法中调用,而OkHttpCall会被传递进CallAdapter,所以CallAdapter是先于Convert被调用的.知道了这点,后续在解决很多业务问题可以是少走点弯路.

retrofit整体调用流程大概如上.

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值