Android之网络请求11————Retrofit的源码分析

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_38499859/article/details/83042782

Android之网络请求11————Retrofit的源码分析

一.前言

前两篇文章主要分析了Retrofit的应用,这一篇主要分析的源码。在分析源码的时候,发现了一篇很好的博客,以及一个讲解视频,这里分享给大家
Retrofit分析-漂亮的解耦套路(视频版)
Android:手把手带你 深入读懂 Retrofit 2.0 源码

二.Retrofit的大致流程分析

一般网络请求的过程:
在这里插入图片描述

Retrofit和上面本质上是差不多的,只不过Retrofit通过使用大量的设计模式进行功能模块的解耦,使得上面的过程更加简单。

在这里插入图片描述

具体过程解释如下:

  1. 通过解析网络请求接口的注解 配置网络请求参数
  2. 通过动态代理生成网络请求对象
  3. 通过网络请求适配器将网络请求对象进行平台适配
  4. 通过网络请求执行器发送网络请求
  5. 通过数据转换器解析服务器返回的数据
  6. 通过回调执行器切换线程(子–>主线程)
  7. 用户在主线程处理返回结果

三.Retrofit的简单使用

关于Retrofir的使用可以看我之前的博客
Android之网络请求8————Retrofit的简单使用

四.源码分析–创建Retrofit实例

1.使用步骤

     //a.创建Retrofit对象
        Retrofit retrofit = new Retrofit.Builder()
                //指定baseurl
                .baseUrl("https://api.douban.com/v2/movie/")
                //设置内容格式,这种对应的数据返回值是String类型
                .addConverterFactory(GsonConverterFactory.create())
                //创建
                .build();

我们在这里简单的创建了一个Retrofit对象,通过链式调用,总共进行了4项。我们一个个来看。

2.Retrofit

先来看Retrofit的构造函数和它所持有的参数

public final class Retrofit {

  //网络请求配置对象的集合。
  //ServiceMethod解析注解
  private final Map<Method, ServiceMethod<?, ?>> serviceMethodCache = new ConcurrentHashMap<>();

   //网络请求器的生产工厂
  final okhttp3.Call.Factory callFactory;
  
  //网络请求的URL对象
  final HttpUrl baseUrl;

  //数据转换器的工厂集合
  final List<Converter.Factory> converterFactories;

  //网络请求适配器的请求工厂集合
  final List<CallAdapter.Factory> callAdapterFactories;

  //回调方法的执行器
  final @Nullable Executor callbackExecutor;

  // 标志位 
  // 作用:是否提前对业务接口中的注解进行验证转换的标志位
  final boolean validateEagerly;

  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;
    this.converterFactories = converterFactories; // Copy+unmodifiable at call site.
    this.callAdapterFactories = callAdapterFactories; // Copy+unmodifiable at call site.
    this.callbackExecutor = callbackExecutor;
    this.validateEagerly = validateEagerly;
  }
}

3.Builder()

来继续看Builder方法

public static final class Builder {
    private final Platform platform;
    private @Nullable okhttp3.Call.Factory callFactory;
    private HttpUrl baseUrl;
    private final List<Converter.Factory> converterFactories = new ArrayList<>();
    private final List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>();
    private @Nullable Executor callbackExecutor;
    private boolean validateEagerly;
    .....
 }

Builder方法中变量基本和Retrofit中的保持一致,所以Retrofit类的成员变量基本上是通过Builder类进行配置

被调用的Builder的构造函数

    Builder(Platform platform) {
     this.platform = platform;
   }

   public Builder() {
     this(Platform.get());
   }

这里可以看出Builder里面设置了默认平台。

查看Platform.get()

class Platform {
  private static final Platform PLATFORM = findPlatform();

  static Platform get() {
    return PLATFORM;
  }

  private static Platform findPlatform() {
    try {
      Class.forName("android.os.Build");
      if (Build.VERSION.SDK_INT != 0) {
         //Android平台
        return new Android(); 
      }
    } catch (ClassNotFoundException ignored) {
    }
    try {
    //Java8
      Class.forName("java.util.Optional");
      return new Java8();
    } catch (ClassNotFoundException ignored) {
    }
    return new Platform();
  }

}

继续来看Android()

 static class Android extends Platform {
    @Override public Executor defaultCallbackExecutor() {
      //默认的回调方法执行器。主要是子线程向主线程切换,并在主线程执行回调方法
      return new MainThreadExecutor();
    }

    @Override CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
      if (callbackExecutor == null) throw new AssertionError();
      return new ExecutorCallAdapterFactory(callbackExecutor);  
      //创建默认的网络请求配置工厂
    }

    static class MainThreadExecutor implements Executor {
      //获取与主线程绑定的Handler
      private final Handler handler = new Handler(Looper.getMainLooper());

      @Override public void execute(Runnable r) {
          // 在UI线程进行对网络请求返回数据处理等操作。
        handler.post(r);
      }
    }
  }

小结:Builder设置了默认的

  • 平台类对象:Android
  • 网络请求适配器工厂:CallAdapterFactory
  • 回调执行器:callbackExecutor

4.baseUrl()

public Builder baseUrl(String baseUrl) {
       //判空处理
      checkNotNull(baseUrl, "baseUrl == null");
      //下面分析
      HttpUrl httpUrl = HttpUrl.parse(baseUrl);
      if (httpUrl == null) {
        throw new IllegalArgumentException("Illegal URL: " + baseUrl);
      }
      //下面分析
      return baseUrl(httpUrl);
    }

继续来看baseUrl(httpUrl)源码

    public Builder baseUrl(HttpUrl baseUrl) {
      checkNotNull(baseUrl, "baseUrl == null");
      //把URL分成几个路径碎片
      List<String> pathSegments = baseUrl.pathSegments();

      //如果URL不是以/结尾就抛出异常
      if (!"".equals(pathSegments.get(pathSegments.size() - 1))) {
        throw new IllegalArgumentException("baseUrl must end in /: " + baseUrl);
      }
      this.baseUrl = baseUrl;
      return this;
    }

小结:

  • baseUrl()用于配置Retrofit类的网络请求url地址

5.addConverterFactory()

继续分析addConverterFactory(GsonConverterFactory.create())语句。首先来看GsonConverterFactory.create()
a.GsonConverterFactory.create()

public final class GsonConverterFactory extends Converter.Factory {
  /**
   * Create an instance using a default {@link Gson} instance for conversion. Encoding to JSON and
   * decoding from JSON (when no charset is specified by a header) will use UTF-8.
   */
  public static GsonConverterFactory create() {
    return create(new Gson());
  }

  /**
   * Create an instance using {@code gson} for conversion. Encoding to JSON and
   * decoding from JSON (when no charset is specified by a header) will use UTF-8.
   */
  @SuppressWarnings("ConstantConditions") // Guarding public API nullability.
  public static GsonConverterFactory create(Gson gson) {
    if (gson == null) throw new NullPointerException("gson == null");
    return new GsonConverterFactory(gson);
  }
  private final Gson gson;

  private GsonConverterFactory(Gson gson) {
    this.gson = gson;
  }

}

GsonConverterFactory.creat()是创建了一个含有Gson对象实例的GsonConverterFactory,并返回给addConverterFactory(),继续来看了addConverterFactory()方法
b.addConverterFactory()

  /** Add converter factory for serialization and deserialization of objects. */
 // 将上面创建的GsonConverterFactory放入到 converterFactories数组
// 在第二步放入一个内置的数据转换器工厂BuiltInConverters()后又放入了一个GsonConverterFactory
    public Builder addConverterFactory(Converter.Factory factory) {
      converterFactories.add(checkNotNull(factory, "factory == null"));
      return this;
    }

总结:这一步中将含有Gson对象实例的GsonConverterFactory并放入到数据转换器工厂converterFactories里

6.build()

  public Retrofit build() {
      if (baseUrl == null) {
        throw new IllegalStateException("Base URL required.");
      }

      //配置call
      //默认使用OkHttp的Call
      okhttp3.Call.Factory callFactory = this.callFactory;
      if (callFactory == null) {
        callFactory = new OkHttpClient();
      }

	  //配置回调方法执行器
	  //如果没有指定,则是使用默认的callbackExecutor
	  //即Android默认的callbackExecutor
      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);
      // 向该集合中添加了步骤2中创建的CallAdapter.Factory请求适配器(添加在集合器末尾)
      callAdapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));


      // Make a defensive copy of the converters.
      //配置数据转换器工厂:converterFactory 
      List<Converter.Factory> converterFactories =
          new ArrayList<>(1 + this.converterFactories.size());

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

	 // 最终返回一个Retrofit的对象,并传入上述已经配置好的成员变量
      return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
          unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
    }

小结:最后一步中,通过前面步骤设置的变量,将Retrofit类的所有成员变量都配置完毕。

7.总结

在构造Retrofit时,通过建造者模式Builder类,具体创建细节就是配置了:

  • 平台类型对象(Platform - Android)
  • 网络请求的url地址(baseUrl)
  • 网络请求工厂(callFactory)
  • 网络请求适配器工厂的集合(adapterFactories)

本质是配置了网络请求适配器工厂- 默认是ExecutorCallAdapterFactory

  • 数据转换器工厂的集合(converterFactories)
  • 回调方法执行器(callbackExecutor)

五.源码分析–创建网络请求接口的实例

1.使用步骤

<-- 步骤1:定义接收网络数据的类 -->
<-- JavaBean.java -->
public class JavaBean {
  .. // 这里就不介绍了
  }

<-- 步骤2:定义网络请求的接口类 -->
public interface RetrofitInterface {
    @GET("in_theaters")
    Call<Theaters> theaters(@QueryMap Map<String ,Object>map);
}

<-- 步骤3:在MainActivity创建接口类实例  -->
  RetrofitInterface retrofitInterface = retrofit.create(RetrofitInterface.class);

直接看retrofit.create的源码

 public <T> T create(final Class<T> service) {
    Utils.validateServiceInterface(service);
    if (validateEagerly) {
     //判断是否需要提前验证
      eagerlyValidateMethods(service);
       // 具体方法作用: 
       // 1. 给接口中每个方法的注解进行解析并得到一个ServiceMethod对象 
       // 2. 以Method为键将该对象存入LinkedHashMap集合中 
       // 特别注意:如果不是提前验证则进行动态解析对应方法(下面会详细说明),得到一个ServiceMethod对象,最后存入到LinkedHashMap集合中,类似延迟加载(默认)
    }


	//创建了网络请求接口的动态代理
	//该动态地理为了拿到网络请求接口实例上的所有注解
    return (T) Proxy.newProxyInstance(
        service.getClassLoader(), //动态实现接口的实现类
        new Class<?>[] { service },//动态创建实例
        new InvocationHandler() {//将代理类的实现交给 InvocationHandler类作为具体的实现
          private final Platform platform = Platform.get();


          // 在 InvocationHandler类的invoke()实现中,除了执行真正的逻辑(如再次转发给真正的实现类对象),还可以进行一些有用的操作
         // 如统计执行时间、进行初始化和清理、对接口调用进行检查等。
          @Override public 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);
            }
            // 作用:读取网络请求接口里的方法,并根据前面配置好的属性配置serviceMethod对象
            //下面详细分析小标题1
            ServiceMethod<Object, Object> serviceMethod =
                (ServiceMethod<Object, Object>) loadServiceMethod(method);

             //作用:根据配置好的serviceMethod对象创建okHttpCall对象 
             //下面分析
            OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);

			//作用:调用OkHttp,并根据okHttpCall返回rejava的Observe对象或者返回Call
            return serviceMethod.adapt(okHttpCall);
          }
        });
  }


  //第五行代码代码的内容
  // 将传入的ServiceMethod对象加入LinkedHashMap<Method, ServiceMethod>集合
  // 使用LinkedHashMap集合的好处:lruEntries.values().iterator().next()获取到的是集合最不经常用到的元素,
  //提供了一种Lru算法的实现
  private void eagerlyValidateMethods(Class<?> service) {
    Platform platform = Platform.get();
    for (Method method : service.getDeclaredMethods()) {
      if (!platform.isDefaultMethod(method)) {
        loadServiceMethod(method);
      }
    }
  }
  

2.loadServiceMethod

// 一个 ServiceMethod 对象对应于网络请求接口里的一个方法
// loadServiceMethod(method)负责加载 ServiceMethod:
 ServiceMethod<?, ?> loadServiceMethod(Method method) {
    ServiceMethod<?, ?> result = serviceMethodCache.get(method);
    if (result != null) return result;

    synchronized (serviceMethodCache) {
    // ServiceMethod类对象采用了单例模式进行创建
      // 即创建ServiceMethod对象前,先看serviceMethodCache有没有缓存之前创建过的网络请求实例
      // 若没缓存,则通过建造者模式创建 serviceMethod 对象
      result = serviceMethodCache.get(method);
      if (result == null) {
        //下面详细分析ServiceMethod
        result = new ServiceMethod.Builder<>(this, method).build();
        serviceMethodCache.put(method, result);
      }
    }
    return result;
  }

我们继续来看ServiceMethod的构造过程

a.ServiceMethod类 构造函数

final class ServiceMethod<R, T> {
  // Upper and lower characters, digits, underscores, and hyphens, starting with a character.
  static final String PARAM = "[a-zA-Z][a-zA-Z0-9_-]*";
  static final Pattern PARAM_URL_REGEX = Pattern.compile("\\{(" + PARAM + ")\\}");
  static final Pattern PARAM_NAME_REGEX = Pattern.compile(PARAM);

  private final okhttp3.Call.Factory callFactory; //网络请求工厂
  private final CallAdapter<R, T> callAdapter;//网络请求适配器

  private final HttpUrl baseUrl
  private final Converter<ResponseBody, R> responseConverter;//内容转换器
  private final String httpMethod;//Http的请求方法
  private final String relativeUrl;//网络请求的相对地址
  private final Headers headers;//http的请求头
  private final MediaType contentType;// 网络请求的http报文body的类型

  //这是三个变量是表明请求体的类型
  private final boolean hasBody;  
  private final boolean isFormEncoded;
  private final boolean isMultipart;
 // 方法参数处理器
  // 作用:负责解析 API 定义时每个方法的参数,并在构造 HTTP 请求时设置参数;
  // 下面会详细说明
  private final ParameterHandler<?>[] parameterHandlers;

  ServiceMethod(Builder<R, T> builder) {
    this.callFactory = builder.retrofit.callFactory();
    this.callAdapter = builder.callAdapter;
    this.baseUrl = builder.retrofit.baseUrl();
    this.responseConverter = builder.responseConverter;
    this.httpMethod = builder.httpMethod;
    this.relativeUrl = builder.relativeUrl;
    this.headers = builder.headers;
    this.contentType = builder.contentType;
    this.hasBody = builder.hasBody;
    this.isFormEncoded = builder.isFormEncoded;
    this.isMultipart = builder.isMultipart;
    this.parameterHandlers = builder.parameterHandlers;
  }

}

b.Builder

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

c.build()

 public ServiceMethod build() {
       // 根据网络请求接口方法的返回值和注解类型,从Retrofit对象中获取对应的网络请求适配器  -->关注点1
      callAdapter = createCallAdapter();
      
      // 根据网络请求接口方法的返回值和注解类型,从Retrofit对象中获取该网络适配器返回的数据类型
      responseType = callAdapter.responseType();
      if (responseType == Response.class || responseType == okhttp3.Response.class) {
        throw methodError("'"
            + Utils.getRawType(responseType).getName()
            + "' is not a valid response body type. Did you mean ResponseBody?");
      }

	 // 根据网络请求接口方法的返回值和注解类型,从Retrofit对象中获取对应的数据转换器 -->关注点3 
	 // 构造 HTTP 请求时,我们传递的参数都是String
	 // Retrofit 类提供 converter把传递的参数都转化为 String
	 // 其余类型的参数都利用 Converter.Factory 的stringConverter 进行转换 
	 // @Body 和 @Part 类型的参数利用Converter.Factory 提供的 requestBodyConverter 进行转换 
	 // 这三种 converter 都是通过“询问”工厂列表进行提供,而工厂列表我们可以在构造 Retrofit 对象时进行添加。
      responseConverter = createResponseConverter();

      // 解析网络请求接口中方法的注解
      // 主要是解析获取Http请求的方法
      // 注解包括:DELETE、GET、POST、HEAD、PATCH、PUT、OPTIONS、HTTP、retrofit2.http.Headers、Multipart、FormUrlEncoded 
      // 处理主要是调用方法 parseHttpMethodAndPath(String httpMethod, String value, boolean hasBody) ServiceMethod中的httpMethod、hasBody、relativeUrl、relativeUrlParamNames域进行赋值
      for (Annotation annotation : methodAnnotations) {
        parseMethodAnnotation(annotation);
      }

      if (httpMethod == null) {
        throw methodError("HTTP method annotation is required (e.g., @GET, @POST, etc.).");
      }

      if (!hasBody) {
        if (isMultipart) {
          throw methodError(
              "Multipart can only be specified on HTTP methods with request body (e.g., @POST).");
        }
        if (isFormEncoded) {
          throw methodError("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; p < parameterCount; p++) {
        Type parameterType = parameterTypes[p];
        if (Utils.hasUnresolvableType(parameterType)) {
          throw parameterError(p, "Parameter type must not include a type variable or wildcard: %s",
              parameterType);
        }
        //为方法中的每个参数创建一个ParameterHandler<?>对象并解析每个参数使用的注解类型
        //该对象的创建过程就是对方法参数中注解进行解析
        //这里的注解包括:Body、PartMap、Part、FieldMap、Field、Header、QueryMap、Query、Path、Url 
        Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
        if (parameterAnnotations == null) {
          throw parameterError(p, "No Retrofit annotation found.");
        }

        parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
      }

      if (relativeUrl == null && !gotUrl) {
        throw methodError("Missing either @%s URL or @Url parameter.", httpMethod);
      }
      if (!isFormEncoded && !isMultipart && !hasBody && gotBody) {
        throw methodError("Non-body HTTP method cannot contain @Body.");
      }
      if (isFormEncoded && !gotField) {
        throw methodError("Form-encoded method must contain at least one @Field.");
      }
      if (isMultipart && !gotPart) {
        throw methodError("Multipart method must contain at least one @Part.");
      }

      return new ServiceMethod<>(this);
    }

关注点1:createCallAdapter()

private CallAdapter<T, R> createCallAdapter() {

      //获取网络请求接口里方法的返回值类型
      Type returnType = method.getGenericReturnType();
      if (Utils.hasUnresolvableType(returnType)) {
        throw methodError(
            "Method return type must not include a type variable or wildcard: %s", returnType);
      }
      if (returnType == void.class) {
        throw methodError("Service methods cannot return void.");
      }
      
      //获取网络请求接口接口里的注解
      Annotation[] annotations = method.getAnnotations();
      try {
        //noinspection unchecked
		//根据网络请求接口方法的返回值和注解类型,从Retrofit对象中获取对应的网络请求
		//关注点2
        return (CallAdapter<T, R>) retrofit.callAdapter(returnType, annotations);
      } catch (RuntimeException e) { // Wide exception range because factories are user code.
        throw methodError(e, "Unable to create call adapter for %s", returnType);
      }
    }

关注点2:CallAdapter<?>

  public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {
    return nextCallAdapter(null, returnType, annotations);
  }

  public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType,
      Annotation[] annotations) {
    checkNotNull(returnType, "returnType == null");
    checkNotNull(annotations, "annotations == null");

    // 创建 CallAdapter 如下
    // 遍历 CallAdapter.Factory 集合寻找合适的工厂(该工厂集合在第一步构造 Retrofit 对象时进行添加(第一步时已经说明))
    // 如果最终没有工厂提供需要的 CallAdapter,将抛出异常
    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;
      }
    }


    //没有找到抛出异常
    StringBuilder builder = new StringBuilder("Could not locate call adapter for ")
        .append(returnType)
        .append(".\n");
    if (skipPast != null) {
      builder.append("  Skipped:");
      for (int i = 0; i < start; i++) {
        builder.append("\n   * ").append(callAdapterFactories.get(i).getClass().getName());
      }
      builder.append('\n');
    }
    builder.append("  Tried:");
    for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
      builder.append("\n   * ").append(callAdapterFactories.get(i).getClass().getName());
    }
    throw new IllegalArgumentException(builder.toString());
  }

关注点3:createResponseConverter()

    private Converter<ResponseBody, T> createResponseConverter() {
      Annotation[] annotations = method.getAnnotations();
      try {
        // responseConverter 还是由 Retrofit 类提供  -->关注点4
        return retrofit.responseBodyConverter(responseType, annotations);
      } catch (RuntimeException e) { // Wide exception range because factories are user code.
        throw methodError(e, "Unable to create converter for %s", responseType);
      }
    }

关注点4:responseBodyConverter()

 public <T> Converter<ResponseBody, T> responseBodyConverter(Type type, Annotation[] annotations) {
    return nextResponseBodyConverter(null, type, annotations);
  }
public <T> Converter<ResponseBody, T> nextResponseBodyConverter(
      @Nullable Converter.Factory skipPast, Type type, Annotation[] annotations) {
    checkNotNull(type, "type == null");
    checkNotNull(annotations, "annotations == null");

    int start = converterFactories.indexOf(skipPast) + 1;
    for (int i = start, count = converterFactories.size(); i < count; i++) {
      
      // 获取Converter 过程:(和获取 callAdapter 基本一致)
      Converter<ResponseBody, ?> converter =
          converterFactories.get(i).responseBodyConverter(type, annotations, this);
      if (converter != null) {
        //noinspection unchecked
        return (Converter<ResponseBody, T>) converter;
         // 遍历 Converter.Factory 集合并寻找合适的工厂(该工厂集合在构造 Retrofit 对象时进行添加(第一步时已经说明))
         // 由于构造Retroifit采用的是Gson解析方式,所以取出的是GsonResponseBodyConverter 
         // Retrofit - Converters 还提供了 JSON,XML,ProtoBuf 等类型数据的转换功能。 
         // 继续看responseBodyConverter() -->关注点5

      }
    }

   //抛出异常
    StringBuilder builder = new StringBuilder("Could not locate ResponseBody converter for ")
        .append(type)
        .append(".\n");
    if (skipPast != null) {
      builder.append("  Skipped:");
      for (int i = 0; i < start; i++) {
        builder.append("\n   * ").append(converterFactories.get(i).getClass().getName());
      }
      builder.append('\n');
    }
    builder.append("  Tried:");
    for (int i = start, count = converterFactories.size(); i < count; i++) {
      builder.append("\n   * ").append(converterFactories.get(i).getClass().getName());
    }
    throw new IllegalArgumentException(builder.toString());
  }

  • 关注点5:responseBodyConverter()**

查看 GsonConverterFactory的实现类


  @Override
  public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
      Retrofit retrofit) {
    TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
    return new GsonResponseBodyConverter<>(gson, adapter);
  }

做数据转换时调用 Gson 的 API 即可。


final class GsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
  private final Gson gson;
  private final TypeAdapter<T> adapter;

  GsonResponseBodyConverter(Gson gson, TypeAdapter<T> adapter) {
    this.gson = gson;
    this.adapter = adapter;
  }

  @Override public T convert(ResponseBody value) throws IOException {
    JsonReader jsonReader = gson.newJsonReader(value.charStream());
    try {
      T result = adapter.read(jsonReader);
      if (jsonReader.peek() != JsonToken.END_DOCUMENT) {
        throw new JsonIOException("JSON document was not fully consumed.");
      }
      return result;
    } finally {
      value.close();
    }
  }
}

3. new OkHttpCall

回到Retrofit的 create函数中,查看 OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);的内容


final class OkHttpCall<T> implements Call<T> {
  private final ServiceMethod<T, ?> serviceMethod; //含有所有请求参数信息的对象
  private final @Nullable Object[] args;//网络请求接口的参数

  private volatile boolean canceled;

  @GuardedBy("this")
  private @Nullable okhttp3.Call rawCall;
  @GuardedBy("this") // Either a RuntimeException, non-fatal Error, or IOException.
  private @Nullable Throwable creationFailure;//几个状态标记位
  @GuardedBy("this")
  private boolean executed;

  OkHttpCall(ServiceMethod<T, ?> serviceMethod, @Nullable Object[] args) {
    this.serviceMethod = serviceMethod;
    this.args = args;
  }
}

4.serviceMethod.adapt(okHttpCall);

回到Retrofit的 create函数中,return serviceMethod.adapt(okHttpCall);中的内容

将第二步创建的OkHttpCall对象传给第一步创建的serviceMethod对象中对应的网络请求适配器工厂的adapt()
adapt()详解

  T adapt(Call<R> call) {
    return callAdapter.adapt(call);
  }

在这里调用了callAdapter的.adapt, Android默认的是Call<>;若设置了RxJavaCallAdapterFactory,返回的则是Observable<>
android默认:

@Override public Call<Object> adapt(Call<Object> call) {
        return new ExecutorCallbackCall<>(callbackExecutor, call);
      }

ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
      //传入上面定义的回调方法执行器
      this.callbackExecutor = callbackExecutor;

      //把上面创建并配置好参数的OkhttpCall对象交给静态代理delegate
      this.delegate = delegate;
    }

Rxjava

@Override public <R> Object adapt(Call<R> call) {
    Observable<Response<R>> responseObservable = new CallObservable<>(call);

    Observable<?> observable;
    if (isResult) {
      observable = new ResultObservable<>(responseObservable);
    } else if (isBody) {
      observable = new BodyObservable<>(responseObservable);
    } else {
      observable = responseObservable;
    }

    if (scheduler != null) {
      observable = observable.subscribeOn(scheduler);
    }

    if (isFlowable) {
      return observable.toFlowable(BackpressureStrategy.LATEST);
    }
    if (isSingle) {
      return observable.singleOrError();
    }
    if (isMaybe) {
      return observable.singleElement();
    }
    if (isCompletable) {
      return observable.ignoreElements();
    }
    return observable;
  }

六.源码分析–生成Call对象

1.使用步骤

 Call<JavaBean> call = NetService.getCall();

2.讲解

  • NetService对象实际上是动态代理对象Proxy.newProxyInstance()(步骤3中已说明),并不是真正的网络请求接口创建的对象
  • 当NetService对象调用getCall()时会被动态代理对象Proxy.newProxyInstance()拦截,然后调用自身的InvocationHandler # invoke()
  • invoke(Object proxy, Method method, Object… args)会传入3个参数:Object proxy:(代理对象),Method method(调用的getCall()),Object… args(方法的参数,即getCall()中的
  • 接下来利用Java反射获取到getCall()的注解信息,配合args参数创建ServiceMethod对象。
  • 最终通过getCall获得的是invoke的返回值。

七.源码分析–执行网络请求

Retrofit默认使用OkHttp,即OkHttpCall类(实现了 retrofit2.Call接口)
OkHttpCall提供了两种网络请求方式:

  • 同步请求:OkHttpCall.execute()
  • 异步请求:OkHttpCall.enqueue()

对于OkHttpCall的enqueue()、execute()的源码,有兴趣可以看看我前面的博客关于OKHttp的源码的文章

1.同步请求

Response<JavaBean> response = call.execute();  

此时call是ExecutorCallbackCall类型,来看其execute()实现

 @Override public Response<T> execute() throws IOException {
      return delegate.execute();
    }

delegete是OkHttpCall类型的,来看其实现

@Override public Response<T> execute() throws IOException {
    okhttp3.Call call;

    synchronized (this) {
      if (executed) throw new IllegalStateException("Already executed.");
      executed = true;

      if (creationFailure != null) {
        if (creationFailure instanceof IOException) {
          throw (IOException) creationFailure;
        } else if (creationFailure instanceof RuntimeException) {
          throw (RuntimeException) creationFailure;
        } else {
          throw (Error) creationFailure;
        }
      }

      call = rawCall;
      if (call == null) {
        try {
        // 步骤1:创建一个OkHttp的Request对象请求 -->关注1
          call = rawCall = createRawCall();
        } catch (IOException | RuntimeException | Error e) {
          throwIfFatal(e); //  Do not assign a fatal error to creationFailure.
          creationFailure = e;
          throw e;
        }
      }
    }

    if (canceled) {
      call.cancel();
    }
     // 步骤2:调用OkHttpCall的execute()发送网络请求(同步)
    // 步骤3:解析网络请求返回的数据parseResponse() -->关注2
    return parseResponse(call.execute());
  }

关注1

 private okhttp3.Call createRawCall() throws IOException {
    // 根据serviceMethod和request对象创建 一个okhttp3.Request
    okhttp3.Call call = serviceMethod.toCall(args);
    if (call == null) {
      throw new NullPointerException("Call.Factory returned null.");
    }
    return call;
  }

关注2

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

    ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);
    try {
      
      /// 等Http请求返回后 & 通过状态码检查后,将response body传入ServiceMethod中,
      //ServiceMethod通过调用Converter接口(之前设置的GsonConverterFactory)
      //将response body转成一个Java对象,即解析返回的数据
      T body = serviceMethod.toResponse(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;
    }
  }

注意:

  • ServiceMethod几乎保存了一个网络请求所需要的数据
  • 发送网络请求时,OkHttpCall需要从ServiceMethod中获得一个Request对象
  • 解析数据时,还需要通过ServiceMethod使用Converter(数据转换器)转换成Java对象进行数据解析

为了提高效率,Retrofit还会对解析过的请求ServiceMethod进行缓存,存放在Map<Method, ServiceMethod> serviceMethodCache = new LinkedHashMap<>();对象中,即第二步提到的单例模式

2.异步请求

使用步骤

 call.enqueue(new Callback<Theaters>() {
            //请求成功时回调
            @Override
            public void onResponse(Call<Theaters> call, Response<Theaters> response) {
            
                response.body().show();
            }

            //请求失败时回调
            @Override
            public void onFailure(Call<Theaters> call, Throwable throwable) {
                Log.e("retrofit", "onFailure: " + throwable);
            }
        });

同上面一样,此次的call是ExecutorCallbackCall类型,来看其execute()实现

@Override public void enqueue(final Callback<T> callback) {
      checkNotNull(callback, "callback == null");

      delegate.enqueue(new Callback<T>() {
        @Override public void onResponse(Call<T> call, final Response<T> response) {
          //切换线程。从而在主线程中显示结果
          callbackExecutor.execute(new Runnable() {
          // 最后Okhttp的异步请求结果返回到callbackExecutor
          // callbackExecutor.execute()通过Handler异步回调将结果传回到主线程进行处理
          //(如显示在Activity等等),即进行了线程切换
            @Override public void run() {
              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(new Runnable() {
            @Override public void run() {
              callback.onFailure(ExecutorCallbackCall.this, t);
            }
          });
        }
      });
    }

此处的delegate是OkHttpCall类型,来继续看enqueue的实现

@Override public void enqueue(final Callback<T> callback) {
    checkNotNull(callback, "callback == null");

    okhttp3.Call call;
    Throwable failure;
  
// 步骤1:创建OkHttp的Request对象,再封装成OkHttp.call
     // delegate代理在网络请求前的动作:创建OkHttp的Request对象,再封装成OkHttp.call
    synchronized (this) {
      if (executed) throw new IllegalStateException("Already executed.");
      executed = true;

      call = rawCall;
      failure = creationFailure;
      if (call == null && failure == null) {
        try {
        // 创建OkHttp的Request对象,再封装成OkHttp.call
         // 方法同发送同步请
          call = rawCall = createRawCall();
        } catch (Throwable t) {
          throwIfFatal(t);
          failure = creationFailure = t;
        }
      }
    }

    if (failure != null) {
      callback.onFailure(this, failure);
      return;
    }

    if (canceled) {
      call.cancel();
    }

// 步骤2:发送网络请求
    // delegate是OkHttpcall的静态代理
    // delegate静态代理最终还是调用Okhttp.enqueue进行网络请求
    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) {
          callFailure(e);
          return;
        }

        try {
          callback.onResponse(OkHttpCall.this, response);
        } catch (Throwable t) {
          t.printStackTrace();
        }
      }

      @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) {
          t.printStackTrace();
        }
      }
    });
  }

那么enqueue是在什么时候继续线程切换的?
线程切换是通过一开始创建Retrofit对象时Platform在检测到运行环境是Android时进行创建的,在前面也进行了分析

static class Android extends Platform {
    @Override public Executor defaultCallbackExecutor() {
     // 返回一个默认的回调方法执行器
      // 该执行器负责在主线程(UI线程)中执行回调方法
      return new MainThreadExecutor();
    }

    // 创建默认的回调执行器工厂
    // 如果不将RxJava和Retrofit一起使用,一般都是使用该默认的CallAdapter.Factory
    @Override CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
      if (callbackExecutor == null) throw new AssertionError();
      return new ExecutorCallAdapterFactory(callbackExecutor);
    }

  // 获取主线程Handler
    static class MainThreadExecutor implements Executor {
      private final Handler handler = new Handler(Looper.getMainLooper());

      @Override public void execute(Runnable r) {
       // Retrofit获取了主线程的handler
        // 然后在UI线程执行网络请求回调后的数据显示等操作。
        handler.post(r);
      }
    }
  }
// 切换线程的流程:
 // 1. 回调ExecutorCallAdapterFactory生成了一个ExecutorCallbackCall对象
  // 2. 通过调用ExecutorCallbackCall.enqueue(CallBack)从而调用MainThreadExecutor的execute()通过handler切换到主线程处理返回结果(如显示在Activity等等)


八.Retrofit源码总结+流程图

1.总结

Retrofit本质是一个一个 RESTful 的HTTP 网络请求框架的封装,即通过 大量的设计模式 封装了 OkHttp ,使得简洁易用。具体过程如下:

  • Retrofit将Http请求抽象成java接口
  • 在接口里用注解描述和配置网络请求参数
  • 用动态代理的方式,动态将网络请求的注解解析成HTTP请求
  • 最后执行HTTP请求

2.源码分析图

在这里插入图片描述

3.流程图

在这里插入图片描述

九.参考资料

Retrofit分析-漂亮的解耦套路(视频版)
Android:手把手带你 深入读懂 Retrofit 2.0 源码

十.文章索引

Android之网络请求1————HTTP协议
Android之网络请求2————OkHttp的基本使用
Android之网络请求3————OkHttp的拦截器和封装
Android之网络请求4————OkHttp源码1:框架
Android之网络请求5————OkHttp源码2:发送请求
Android之网络请求6————OkHttp源码3:拦截器链
Android之网络请求7————OkHttp源码4:网络操作
Android之网络请求8————OkHttp源码5:缓存相关
Android之网络请求9————Retrofit的简单使用
Android之网络请求10————Retrofit的进阶使用
Android之网络请求11————Retrofit的源码分析

展开阅读全文

没有更多推荐了,返回首页