读读retrofit源码_Android

okhttp官网
okhttp github
retrofit官网
retrofit github

使用retrofit之前,必须先会基本使用okhttp来请求网络资源,才能理解retrofit的工作原理。
okhttp使用教程挺多的,参考:Android OkHttp完全解析 是时候来了解OkHttp了

okhttp简单用法示例如下:
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

private OkHttpClient okHttpClient = new OkHttpClient();

private void httpGet() {
        Request request = new Request.Builder()
                .url("http://www.163.com")
                .build();

        Call call = okHttpClient.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {

            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                String htmlStr = response.body().string();
                Log.d("API", htmlStr);
            }
        });
    }

可以看到,请求一个网络url前,需要先构建出okhttp3.Request, okhttp3.Call, Retrofit的主线工作流程就是干这个的。构建出请求,丢给okhttp,然后取得返回数据,复杂的网络工作都交给okhttp来做。

本文分析源码所使用的版本

implementation 'com.squareup.okhttp3:okhttp:3.12.3'
implementation 'com.squareup.retrofit2:retrofit:2.4.0'

下面从retrofit最简单的使用例子开始,暂时不使用RxJava, Gson等,避免增加复杂度,直接获取okhttp3.ResponseBody是最简单的写法了。
(retrofit的使用教程也挺多的,参考:Android Retrofit 2.0 的详细 使用攻略)

先定义一个接口ApiService:
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.http.GET;

public interface ApiService {

    // @GET注解的作用:采用Get方法发送网络请求
    // 如果想直接获得Responsebody中的内容,可以定义网络请求返回值为Call<ResponseBody>
    @GET("/")
    Call<ResponseBody> getNewsHot();
}

然后:

private OkHttpClient okHttpClient = new OkHttpClient();

private void retrofitGet() {
        Retrofit retrofit = new Retrofit.Builder()
                .client(okHttpClient)
                .baseUrl("http://www.163.com")
                .build();

        ApiService service = retrofit.create(ApiService.class);
        
        retrofit2.Call<ResponseBody> newsHot = service.getNewsHot();
        newsHot.enqueue(new retrofit2.Callback<ResponseBody>() {
            @Override
            public void onResponse(retrofit2.Call<ResponseBody> call, retrofit2.Response<ResponseBody> response) {
                try {
                    Log.d("API", "response:"+response.body().string());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            @Override
            public void onFailure(retrofit2.Call<ResponseBody> call, Throwable t) {

            }
        });
    }

这里,神奇的事情发生了:retrofit.create(ApiService.class),传进去一个ApiService.class, 又返回一个ApiService service,然后service.getNewsHot().enqueue(new Callback…)就能获得数据了。上面总共10来行代码,其实底下很复杂,咱们来一点一点地抠代码进行学习。
首先,把retrofit源码下载下来,放进自己的项目中,方便断点,以及打印日志来观察。

下面来分析每一行代码:
Retrofit retrofit = new Retrofit.Builder()
                .client(okHttpClient)
                .baseUrl("http://www.163.com")
                .build();

先看Retrofit类的成员变量

public final class Retrofit {
  /**
   *  一个Map, 缓存了Method和类ServiceMethod的键值对
   *  Method是什么, 就是ApiService里面的getNewsHot等方法.
   *  ServiceMethod是什么,这里刚开始看源码,只需要知道它是跟Method一一对应的java类,
   *  大概是用于将service里面的method转换成okhttp3.Request的就行了,后面要深入细看
   */
  private final Map<Method, ServiceMethod<?, ?>> serviceMethodCache = new ConcurrentHashMap<>();

  /**
   *  callFactory: Call生成工厂。谁可以生成Call请求啊,只有okhttp可以,retrofit本身只是将请求参数转换成Request,是没法直接生成Call的,
   *  所以callFactory就是okHttpClient。 注意这里的Call是okhttp3中的
   */
  final okhttp3.Call.Factory callFactory;
  
  /** 
   * 网络请求的url地址,如 "http://www.163.com"
   */
  final HttpUrl baseUrl;

  /**
   *  callAdapterFactories:Call适配器工厂。就是要根据每个方法的返回值,比如Call<ResponseBody> getNewsHot();
   *  这里的返回值就是Call<ResponseBody>,  在调用service.getNewsHot() 方法时,此适配器工厂用来返回一个实现
   *  Call<T>接口的对象,  如:  retrofit2.Call<ResponseBody> newsHot = service.getNewsHot();
   *  注意这里的Call是retrofit中的
   */
  final List<CallAdapter.Factory> callAdapterFactories;

  /**
   * 数据转换器工厂, 即返回的数据交给哪个转换器来转换。
   * 这里要注意的是找到第一个适合的转换器就直接使用,后面的不会再使用, 所以添加时要注意顺序
   */
  final List<Converter.Factory> converterFactories;
  /**
	* 回调方法执行器
 	*/
  final @Nullable Executor callbackExecutor;

final boolean validateEagerly;

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

可以看到,我们必须先实例化一个Retrofit类对象,并将各个成员初始化,才能使用它。那么怎样生成这个对象并初始化它呢, 使用Builder构造模式:

Retrofit retrofit = new Retrofit.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(Platform platform) {
      this.platform = platform;
    }

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

    Builder(Retrofit retrofit) {
      ...
    }

Builder类的成员变量platform初始化为Platform的子类Android, 其实Platform就是一个普通的java类,里面定义了两个方法:
Executor defaultCallbackExecutor()
CallAdapter.Factory defaultCallAdapterFactory(Executor callbackExecutor)
这两个方法都已经被Platform的子类Android重写,目前就知道这么多就行了。

 Retrofit retrofit = new Retrofit.Builder()
                .client(okHttpClient)

okHttpClient被赋值为Retrofit的成员变量callFactory, Call生成工厂,上面已说过。

Retrofit retrofit = new Retrofit.Builder()
                .client(okHttpClient)
                .baseUrl("http://www.163.com")

设置Retrofit的成员变量baseUrl

Retrofit retrofit = new Retrofit.Builder()
                .client(okHttpClient)
                .baseUrl("http://www.163.com")
                .build();

重点来了!!! 调用build()来生成Retrofit对象:

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.add(platform.defaultCallAdapterFactory(callbackExecutor));

      // Make a defensive copy of the converters.
      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);

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

①callFactory就是okhttpclient, 没啥好说的

② callbackExecutor=platform.defaultCallbackExecutor(),Executor是一个接口

public interface Executor {
    void execute(Runnable command);
}

由Platform的子类Android实现, 就是用Handler在主线程执行一个Runnable,很常见的用法:

static class Android extends Platform {
    @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);
      }
    }
  }

③ 只需要知道callAdapterFactories这个list, 里面增加了一个对象就行了,这个对象实现了CallAdapter.Factory接口,做为默认的callAdapterFactory , 没继续往下读代码是看不懂它的作用的。

④ 增加了一项默认数据转换器 BuiltInConverters, 而converterFactories在这里是空的,忽略它。

⑤ 直接用构造函数生成Retrofit对象,结束。

折腾了半天, 才终于生成一个对象,就问你累不累??!!!

下面可以开始使用这个对象了
ApiService service = retrofit.create(ApiService.class);

用到了动态代理模式JAVA反射_代理, 这行代码简单, 任何人都能写出,下一行代码才是整个Retrofit的精华,就跟魔法一样,看到了就会觉得哇!哇!哇!,原来写代码还可以这样,简直不可思议,出神入化:

retrofit2.Call<ResponseBody> newsHot = service.getNewsHot();

调用这行代码,实际就是调用动态代理里的InvocationHandler里面的方法:

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    return method.invoke(this.target, args);
}

这里要开始思考了, 接下来的并不是普通的代码, 是大神写的,大神写的代码不是那么容易看懂的, 各种你没见过的代码技巧,极致优化,反射/注解, 复杂得一B,大神的脑回路都跟常人的不同,如果陷入代码细节里,估计一时半会都出不来了。所以我们要抓住主线来看,有的放矢,才不会迷失。
首先, 我们的目的是要创建一个实现了retrofit2.Call<T>接口的newsHot对象,T的实际类型为ResponseBody。那么在invoke()方法里面, 我们就应该返回一个实现了retrofit2.Call<ResponseBody>接口的对象。注意,这里说的要实现什么接口,返回什么类型, 都是我们看前面的代码处于程序员的视角才知道的,但在invoke()方法里面,只有三个参数(Object proxy, Method method, Object[] args), 所有的信息都只能从这三个参数中获得,这就必须通过反射和注解来获取这些信息。

现在来详细看invoke()方法里面的代码:

@SuppressWarnings("unchecked") // Single-interface proxy creation guarded by parameter safety.
  public <T> T create(final Class<T> service) {
    Utils.validateServiceInterface(service);
    if (validateEagerly) {
      eagerlyValidateMethods(service);
    }
    return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
        new InvocationHandler() {
          private final Platform platform = Platform.get();

          @Override public Object invoke(Object proxy, Method method, @Nullable Object[] args)
              throws Throwable {
            // 省略代码...
            ServiceMethod<Object, Object> serviceMethod =
                (ServiceMethod<Object, Object>) loadServiceMethod(method);
            OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
            return serviceMethod.adapt(okHttpCall);
          }
        });
  }

首先我们要获得一个ServiceMethod类,如果在serviceMethodCache缓存里没找到就生成一个:

ServiceMethod<?, ?> loadServiceMethod(Method method) {
    ServiceMethod<?, ?> result = serviceMethodCache.get(method);
    if (result != null) return result;

    synchronized (serviceMethodCache) {
      result = serviceMethodCache.get(method);
      if (result == null) {
        result = new ServiceMethod.Builder<>(this, method).build();
        serviceMethodCache.put(method, result);
      }
    }
    return result;
  }

怎样生成ServiceMethod对象, 套路就跟前面生成Retrofit对象一样, 使用Builder构造模式。那么老规矩,先看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);
 
  /**
   *  callFactory: 肯定引用了前面Retrofit对象的成员变量callFactory
   */
  private final okhttp3.Call.Factory callFactory;
  
   /**
   *  这里要一定好好理解清楚,把该接口的英文注释读得明明白白。
   *  callAdapter的作用:Adapts a {@link Call} with response type {@code R} into the type of {@code T}.
   *  就是将一个Call<R>转换成另一个东东T,   实际就是将Call<ResponseBody> 转换成 T
   */
  private final CallAdapter<R, T> callAdapter;
  
  /**
   *  baseUrl: 肯定引用了前面Retrofit对象的成员变量baseUrl,这里也可以推论出,每个Retrofit对象都有不同的baseUrl, 每个Retrofit对象下的方法
   *  都应该共用同一个baseUrl, 接口ApiService内所有方法都应访问相同的baseUrl
   */
  private final HttpUrl baseUrl;
  
  /**
  * Response内容转换器  
  * 作用:负责把服务器返回的数据流(可能为字符串或二进制数据) 转化为R 类型的对象
  */
  private final Converter<ResponseBody, R> responseConverter;
  /*
  * 网络请求的Http方法, 看这里就知道,一个网络访问必定含有httpMethod,所以一个ServiceMethod就会转换一个okhttp的Request网络请求,
  *  一一对应。前面也提过,Retrofit的主线工作就是构建okhttp的Request请求
  */
  private final String httpMethod;
  private final String relativeUrl; // 网络请求的相对地址  
  private final Headers headers;// 网络请求的http请求头 键值对  
  private final MediaType contentType;// 网络请求的http报文body的类型
  private final boolean hasBody;//是否含有body
  private final boolean isFormEncoded;//表单是否encode
  private final boolean isMultipart;//Multipart,多字段上传时使用
  /**
  *  方法参数处理器
  *  作用:负责解析 ApiService 定义时每个方法的参数,并在构造 HTTP 请求时设置参数;
  *  下面会详细说明
  */
  private final ParameterHandler<?>[] parameterHandlers;

  // 说明:从上面的成员变量可以看出,ServiceMethod对象包含了访问网络的所有基本信息

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

通过Builder构造模式来生成对象:
result = new ServiceMethod.Builder<>(this, method).build();

这里要用到注解的知识了JAVA反射_注解, 以及Java TypeJAVA反射_TYPE类型

static final class Builder<T, R> {
    final Retrofit retrofit;
    final Method method;
    final Annotation[] methodAnnotations;
    final Annotation[][] parameterAnnotationsArray;
    final Type[] parameterTypes;

    Type responseType;
    boolean gotField;
    boolean gotPart;
    boolean gotBody;
    boolean gotPath;
    boolean gotQuery;
    boolean gotUrl;
    String httpMethod;
    boolean hasBody;
    boolean isFormEncoded;
    boolean isMultipart;
    String relativeUrl;
    Headers headers;
    MediaType contentType;
    Set<String> relativeUrlParamNames;
    ParameterHandler<?>[] parameterHandlers;
    Converter<ResponseBody, T> responseConverter;
    CallAdapter<T, R> callAdapter;

	Builder(Retrofit retrofit, Method method) {
      this.retrofit = retrofit;
      //前面的getNewsHot方法
      this.method = method; 
      
      //获取方法的所有注解,返回一个数组,getNewsHot方法只有一个注解@GET("/")
      this.methodAnnotations = method.getAnnotations(); 
      
	 //获取方法参数的参数化类型数组Type[] (注意与getParameterTypes的区别)。
	 //例如,如果有两个参数, 参数1是String类型, 参数2是List<String>, 
	 //Type[0]就是java.lang.String, Type[1]就是java.util.List<java.lang.String>
      this.parameterTypes = method.getGenericParameterTypes();

	  //getParameterAnnotations返回按参数顺序的二维数组,每个参数的对应一个一维注解数组,如果该参数没有注解,则该一维数组长度为零
      this.parameterAnnotationsArray = method.getParameterAnnotations();
    }

   public ServiceMethod build() {
      callAdapter = createCallAdapter();
      
     //responseType就是ResponseBody类型
      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?");
      }
      responseConverter = createResponseConverter();

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

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

createCallAdapter()方法:

private CallAdapter<T, R> createCallAdapter() {
      //获取方法返回的泛型类型 Call<ResponseBody>
      Type returnType = method.getGenericReturnType();
      Log.d("kkunion", "ServiceMethod createCallAdapter returnType:"+returnType);

      //hasUnresolvableType判断是否能处理该方法的返回类型, Utils工具类里面
      //这里只说一下getActualTypeArguments方法,用于拿到Call<ResponseBody>中的ResponseBody,
      // ResponseBody是一个实际的类,所以if (type instanceof Class<?>) {return false}, 流程继续往下走
      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
        //把Call<ResponseBody> returnType, @GET("/") annotations传进去
        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);
      }
    }

现在要回头看Retrofit对象,前面说过

③ 只需要知道callAdapterFactories这个list, 里面增加了一个对象就行了,这个对象实现了CallAdapter.Factory接口,做为默认的callAdapterFactory , 没继续往下读代码是看不懂它的作用的。

前面我们已经知道callAdapterFactories这个list,里面有一个对象了。这个对象干嘛用的,就是会传进去method的returnType,看该对象能不能处理。该对象是CallAdapter.Factory的子类,如果重写了public abstract @Nullable CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit),并且不返回null,就表明该对象可以处理returnType。如果callAdapterFactories这个list里面有多个对象,则按顺序遍历看哪个可以处理。Retrofit.Builder里面就有一个方法可以往这个list添加对象,public Builder addCallAdapterFactory(CallAdapter.Factory factory) 。

这里list里面对象就是ExecutorCallAdapterFactory

final class ExecutorCallAdapterFactory extends CallAdapter.Factory {
  final Executor callbackExecutor;

  ExecutorCallAdapterFactory(Executor callbackExecutor) {
    this.callbackExecutor = callbackExecutor;
  }

  @Override
  public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
  //获取Call<ResponseBody>前面的Call, 即<>前面的类型
    if (getRawType(returnType) != Call.class) {
     //如果不是Call<T>形式的,返回null,表示处理不了该类型
      return null;
    }
    //responseType就是ResponseBody类型
    final Type responseType = Utils.getCallResponseType(returnType);
    
    //重点: 这里返回了一个实现了CallAdapter<R, T>接口的对象SMO(简称), SMO里面有两个方法可以调用:
    //一、Type responseType()
    //二、Call<Object> adapt(Call<Object> call)  , 这个方法接收一个实现了retrofit2.Call<T> extends Cloneable接口的对象RCO(简称),
    //该方法返回一个实现了retrofit2.Call<T>接口的对象UCO(简称), 对UCO的操作, 就相当于对传进来RCO的操作
    //UCO返回给用户使用,就是getNewsHot方法的返回值, 即对应了前面的代码:  retrofit2.Call<ResponseBody> newsHot = service.getNewsHot();
    
    return new CallAdapter<Object, Call<?>>() {
      @Override public Type responseType() {
        return responseType;
      }

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

  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) {
      checkNotNull(callback, "callback == null");

      delegate.enqueue(new Callback<T>() {
        @Override public void onResponse(Call<T> call, final Response<T> response) {
          callbackExecutor.execute(new Runnable() {
            @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);
            }
          });
        }
      });
    }

    @Override public boolean isExecuted() {
      return delegate.isExecuted();
    }

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

    @Override public void cancel() {
      delegate.cancel();
    }

    @Override public boolean isCanceled() {
      return delegate.isCanceled();
    }

    @SuppressWarnings("CloneDoesntCallSuperClone") // Performing deep clone.
    @Override public Call<T> clone() {
      return new ExecutorCallbackCall<>(callbackExecutor, delegate.clone());
    }

    @Override public Request request() {
      return delegate.request();
    }
  }
}

那么谁来调用T adapt(Call<R> call) {}这个方法, 就是前面的invoked方法动态代理里面

 @Override public Object invoke(Object proxy, Method method, @Nullable Object[] args)
              throws Throwable {
            // 省略代码...
            ServiceMethod<Object, Object> serviceMethod =
                (ServiceMethod<Object, Object>) loadServiceMethod(method);
            OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
            return serviceMethod.adapt(okHttpCall);
          }

再回顾下前面的代码
retrofit2.Call<ResponseBody> hot = service.getNewsHot("1");
这样就能看出来了,hot对象其实就是UCO(简称), OkHttpCall<Object> okHttpCall就是RCO(简称),ExecutorCallbackCall就是SMO(简称)。对UCO的操作, 就是操作SMO, 间接操作RCO。 那么OkHttpCall是什么呢, 这里还不能进去看,因为OkHttpCall要用到ServiceMethod其他的方法,要先分析完

继续看回ServiceMethod类中的代码, 获取一个数据转换器
responseConverter = createResponseConverter();

Retrofit对象中,前面说过

④ 增加了一项默认数据转换器 BuiltInConverters, 而converterFactories在这里是空的,忽略它。

前面我们已经知道converterFactories这个list,里面有一个对象BuiltInConverters了。这个对象干嘛用的,就是会将Call<ResponseBody>中的ResponseBody作为Type给该对象,看该对象能不能处理该类型Type,。该对象是Converter.Factory的子类,如果重写了public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit),并且不返回null,就表明该对象可以处理类型Type。如果converterFactories这个list里面有多个对象,则按顺序遍历看哪个可以处理。Retrofit.Builder里面就有一个方法可以往这个list添加对象,public Builder addConverterFactory(Converter.Factory factory) 。

这里list里面对象就是BuiltInConverters

final class BuiltInConverters extends Converter.Factory {
  @Override
  public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
      Retrofit retrofit) {
      
      //从网络返回数据时, 表明可以处理ResponseBody这种格式
      //实际需要转换时,就会调用该对象的T convert(F value) throws IOException方法
      //参看BufferingResponseBodyConverter
    if (type == ResponseBody.class) {
      return Utils.isAnnotationPresent(annotations, Streaming.class)
          ? StreamingResponseBodyConverter.INSTANCE
          : BufferingResponseBodyConverter.INSTANCE;
    }
    if (type == Void.class) {
      return VoidResponseBodyConverter.INSTANCE;
    }
    return null;
  }

  //发送数据到网络前, 是否对RequestBody数据做另外的处理
  //RequestBodyConverter没有做处理,直接发送RequestBody
  @Override
  public Converter<?, RequestBody> requestBodyConverter(Type type,
      Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
    if (RequestBody.class.isAssignableFrom(Utils.getRawType(type))) {
      return RequestBodyConverter.INSTANCE;
    }
    return null;
  }

  // 处理Call<Void>这种格式
  static final class VoidResponseBodyConverter implements Converter<ResponseBody, Void> {
    static final VoidResponseBodyConverter INSTANCE = new VoidResponseBodyConverter();

    @Override public Void convert(ResponseBody value) {
      value.close();
      return null;
    }
  }

  // 没有做处理,直接发送RequestBody
  static final class RequestBodyConverter implements Converter<RequestBody, RequestBody> {
    static final RequestBodyConverter INSTANCE = new RequestBodyConverter();

    @Override public RequestBody convert(RequestBody value) {
      return value;
    }
  }
  
  // 处理声明了Streaming注解的格式
  static final class StreamingResponseBodyConverter
      implements Converter<ResponseBody, ResponseBody> {
    static final StreamingResponseBodyConverter INSTANCE = new StreamingResponseBodyConverter();

    @Override public ResponseBody convert(ResponseBody value) {
      return value;
    }
  }

  //处理Call<ResponseBody>这种格式
  static final class BufferingResponseBodyConverter
      implements Converter<ResponseBody, ResponseBody> {
    static final BufferingResponseBodyConverter INSTANCE = new BufferingResponseBodyConverter();

    @Override public ResponseBody convert(ResponseBody value) throws IOException {
      try {
        // Buffer the entire body to avoid future I/O.
        return Utils.buffer(value);
      } finally {
        value.close();
      }
    }
  }

  static final class ToStringConverter implements Converter<Object, String> {
    static final ToStringConverter INSTANCE = new ToStringConverter();

    @Override public String convert(Object value) {
      return value.toString();
    }
  }
}

继续看回ServiceMethod类中的代码, 下面主要是用来获取注解中的信息, 代码很长很长,是个苦力活

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);
        }
		//解析参数的注解
        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);

注解分析完成后,最后会得到这些信息:
httpMethod, baseUrl, relativeUrl, headers, contentType, hasBody, isFormEncoded, isMultipart

ServiceMothod中还有一个方法toCall, 就是根据httpMothod, baseUrl, relativeUrl…等信息,去构建出一个okhttp3.Call来返回:

/** Builds an HTTP request from method arguments. */
  okhttp3.Call toCall(@Nullable Object... args) throws IOException {
    RequestBuilder requestBuilder = new RequestBuilder(httpMethod, baseUrl, relativeUrl, headers,
        contentType, hasBody, isFormEncoded, isMultipart);

    @SuppressWarnings("unchecked") // It is an error to invoke a method with the wrong arg types.
    ParameterHandler<Object>[] handlers = (ParameterHandler<Object>[]) parameterHandlers;

    int argumentCount = args != null ? args.length : 0;
    if (argumentCount != handlers.length) {
      throw new IllegalArgumentException("Argument count (" + argumentCount
          + ") doesn't match expected count (" + handlers.length + ")");
    }

    for (int p = 0; p < argumentCount; p++) {
      handlers[p].apply(requestBuilder, args[p]);
    }

    return callFactory.newCall(requestBuilder.build());
  }

那么构建出来的okhttp3.Call是给谁使用的呢, 给OkHttpCall这个类使用。我们已经知道OkHttpCall是动态代理对象,它能干的活就是Call<T>中定义的接口:

public interface Call<T> extends Cloneable {

  Response<T> execute() throws IOException;

  void enqueue(Callback<T> callback);

  boolean isExecuted();

  void cancel();

  boolean isCanceled();

  Call<T> clone();

  Request request();
}

先来看void enqueue(Callback callback);

@Override 
public void enqueue(final Callback<T> callback) {
    checkNotNull(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 {
        // 调用ServiceMethod的方法toCall, 构建一个okhttp3.Call
          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 {
        // 从okhttp3.Response转换成retrofit2.Response
          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();
        }
      }
    });
  }

private okhttp3.Call createRawCall() throws IOException {
    okhttp3.Call call = serviceMethod.toCall(args);
    if (call == null) {
      throw new NullPointerException("Call.Factory returned null.");
    }
    return call;
  }

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 {
      //这里就用到了前面分析的数据转换器BuiltInConverters
      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;
    }
  }

看到这里,我们已经拿到网络数据,并转换成我们所需要的格式了,流程基本结束了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值