Retrofit2.0- 源码分析

1. 阅读引导

在分析 Retrofit 源码之前,你首先得理解动态代理模式,因为Retrofit是通过动态代理的方式进行统一网络请求接口类的处理。Retrofit的代码量并不大,只是对OkHttp进行了封装,用更少的代码进行网络请求,明白动态代理模式之后,再看Retrofit网络请求处理流程就很清楚了。少量的代码使用大量的设计模式,所以Retrofit框架很值得我们去研究。

2. Retrofit基本使用

  1. 配置Retrofit对象(与OkHttp相同,采用Builder模式)

Retrofit retrofit = new Retrofit.Builder().baseUrl(“xxxxx”).build();

  1. 创建请求接口类
  public interface NetworkInterface {
    
    @GET("...")
    Call<MyResponse> listRepos(); //不同的方法代表不同的网络请求,可以声明请求方式(GET、POST..),请求头Header参数,请求体信息。
    
    ....
}
  1. 创建接口类实例

NetworkInterface networkInterface = retrofit.create(NetworkInterface.class);

  1. 调用方法,请求实际的网络请求
 Call<MyResponse> call = networkInterface.listRepos();
 call.enqueue(new Callback<MyResponse>() {  //与OkHttp不同,异步请求会回调到主线程
            @Override
            public void onResponse(Call<MyResponse> call, Response<MyResponse> response) { }

            @Override
            public void onFailure(Call<MyResponse> call, Throwable t) { }
        });

3. Retrofit流程图

《Retrofit2.0- 源码分析》 Retrofit请求处理流程图.PNG

说明: Retrofit只存在一个CallFactory,但是存在多个CallAdapterFactory和ConvertFactory,针对不同的请求接口方法,Retrofit会通过其返回值,选择特定的CallAdapterFactory和CovertFactory。

4. Retrofit源码分析

4.1 Retrofit创建过程

通过前面基本的使用代码可以看出,Retrofit的创建也是采用Builder设计模式,通过new Retrofit.Builder().build()。我们先看看new Retrofit.Builder()的初始化工作。

public static final class Builder {
  ... 
   public Builder() {
      this(Platform.get());
    }

   Builder(Platform platform) {
      converterFactories.add(new BuiltInConverters());
    }
  ...
}

通过Platform.get()获取当前平台对象Platform,然后调用它的另一个构造器,在这个构造器中,为ConvertFactory集合添加一个默认的ConvertFactory,不同的ConvertFactory产生的Convert对OkHttp网络请求返回的Response转化处理不一样,而默认ConvertFactory的Convert并没有对Response做太多处理,获得的数据依旧是Response对象。通过Builder.addConverterFactory(xxx)添加更多的ConvertFactory,比如xxx替换为GsonConverterFactory.create()添加GsonConvertFatory,它产生的GsonConvert就能将Response映射成JavaBean实体。

回到主流程,还是看看Platform.get()是如何处理的吧!

class Platform {

  private static final Platform PLATFORM = findPlatform();        //  静态工厂模式!

  static Platform get() {
    return PLATFORM;
  }

  private static Platform findPlatform() {     // 识别当前平台,如果是Android,就直接返回Android()对象实例
    try {
      Class.forName("android.os.Build");
      if (Build.VERSION.SDK_INT != 0) {
        return new Android();
      }
    } catch (ClassNotFoundException ignored) {
    }
     ...
   
    static class Android extends Platform {                    // Platform的子类,Android平台对象类
    @Override public Executor defaultCallbackExecutor() {
      return new MainThreadExecutor();
    }

    @Override CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) {   // 获取Android平台的默认CallAdapterFactory对象
      if (callbackExecutor == null) throw new AssertionError();
      return new ExecutorCallAdapterFactory(callbackExecutor);
    }

    static class MainThreadExecutor implements Executor {       // 获取Android平台的默认线程执行调度器,其实就是通过Handler用于线程切换。
      private final Handler handler = new Handler(Looper.getMainLooper());

      @Override public void execute(Runnable r) {
        handler.post(r);
      }
    }
  }
  
  }

总结: 通过new Retrofit.Builder()为ConvertFactory集合中添加一个默认ConvertFactory,创建一个包含默认的CallAdapterFactory、Executor的Android平台对象。注意,默认的ConvertFactory已经添加到了ConvertFactory集合中了,但是Android对象中的CallAdapterFactory并没有加入到CallAdapterFactory集合中。

接着看new Retrofit.Builder().build()中的build()方法:

public Retrofit build() {
      if (baseUrl == null) {                  // 强制需要通过.baseUrl("xxxxx")配置url
        throw new IllegalStateException("Base URL required.");  
      }

      okhttp3.Call.Factory callFactory = this.callFactory;
      if (callFactory == null) {
        callFactory = new OkHttpClient();    // 创建CallFactory用于生产Call对象,从这里也可以看出Retrofit最终还是通过OkHttp发送网络请求
      }

      Executor callbackExecutor = this.callbackExecutor;
      if (callbackExecutor == null) {
        callbackExecutor = platform.defaultCallbackExecutor();    // 获取Android平台对象中的默认Executor,里面通过Handler进行线程切换,上面有讲过!
      }

      List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);

         // 此处将Android平台对象中的CallAdapterFactory添加到Retrofit的CallAdapterFactory集合中.
         // 注意同时将Executor也传入到这个CallAdapterFactory中,那么工厂生产出来的CallAdapter就也就具有线程切换的能力。
       adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor)); 

      List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);

      return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
          callbackExecutor, validateEagerly);                  // 通过Builder创建Retrofit,并将配置参数作为参数传入
    }

再看看一下Retrofit的构造:

  Retrofit(okhttp3.Call.Factory callFactory, HttpUrl baseUrl,
      List<Converter.Factory> converterFactories, List<CallAdapter.Factory> adapterFactories,
      @Nullable Executor callbackExecutor, boolean validateEagerly) { 

    this.callFactory = callFactory;
    this.baseUrl = baseUrl;
    this.converterFactories = unmodifiableList(converterFactories); // Defensive copy at call site.
    this.adapterFactories = unmodifiableList(adapterFactories); // Defensive copy at call site.
    this.callbackExecutor = callbackExecutor;
    this.validateEagerly = validateEagerly;
  }
4.2 核心动态代理代码

NetworkInterface networkInterface = retrofit.create(NetworkInterface.class);

public <T> T create(final Class<T> service) {
    Utils.validateServiceInterface(service);              //  1.   判断网络请求接口类的合法性

    if (validateEagerly) {                                  //   2.   是否需要提前对 网络请求接口类 中的方法进行提前处理,即为接口中的每一个方法提前处理成 SeviceMethod(核心类)对象,并缓存。
      eagerlyValidateMethods(service);
    }
                                               //   3. 生成动态代理类
    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 {
              ... 
                                                 // 4. 将接口中的方法处理成serviceMethod。
             ServiceMethod<Object, Object> serviceMethod =  (ServiceMethod<Object, Object>) loadServiceMethod(method); 
            OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);  // 5. 创建 OkHttpCall对象,传入serviceMethod对象和调用方法实际参数。 
            return serviceMethod.callAdapter.adapt(okHttpCall);  // 6. 将Call对象进行CallAdapter进行转化( 比如RxCallAdapter将Call转化为Observable ) 注意Call还没有被执行,即没有进行网络请求。
          }
        });
  }

总结:
(一 ) retrofit.create(xx)方法中处理分三步:

    1. 判断网络请求接口类的合法性
    1. 是否需要提前对 网络请求接口类 中的方法进行预处理
    1. 返回生成动态代理类

(二) 调用网络请求接口方法,动态代理类中的invoke()方法被执行,也处理也分三步:

    1. 将对应的执行方法转化成ServiceMethod对象
    1. 创建OkHttpCall对象
  • 3 OkHttpCall通过CallAdapter进行Call的转化
4.3 调用接口方法

Call<MyResponse> call = networkInterface.listRepos();

在通过上面的说明,当调用网络请求接口类方法时,就会调用invoke方法,传入通过反射获取Method和执行方法参数args,因为没有调用call.execute()或call.enqueue(Callback),所以Call并没有执行。接下来我们具体看看invoke方法体中三部曲吧!

    1. 将对应的执行方法转化成ServiceMethod对象
  ServiceMethod<?, ?> loadServiceMethod(Method method) {
    ServiceMethod<?, ?> result = serviceMethodCache.get(method);  // 先从缓存中取,如果在之前分析的create()中validateEagerly = true 必然从缓存中能取到。
    if (result != null) return result;

    synchronized (serviceMethodCache) {
      result = serviceMethodCache.get(method);
      if (result == null) {
        result = new ServiceMethod.Builder<>(this, method).build();  // 根据Method创建ServiceMethod对象
        serviceMethodCache.put(method, result);        // 将创建的ServiceMethod进行缓存
      }
    }
    return result;
  }

接下来看看,ServiceMethod的创建!

ServiceMethodBuilder.class

 Builder(Retrofit retrofit, Method method) {
      this.retrofit = retrofit;                         // 1. 将外观类 Retrofit传入
      this.method = method;                       
      this.methodAnnotations = method.getAnnotations();  //  2. 获取方法上的注解(@GET @POST... )
      this.parameterTypes = method.getGenericParameterTypes();   
      this.parameterAnnotationsArray = method.getParameterAnnotations();  // 3. 获取参数注解(@Query ...)
    }

public ServiceMethod build() {
      callAdapter = createCallAdapter();               // 4. 获取该方法对应的CallAdapter
      responseType = callAdapter.responseType();  //  5. 获取该方法的响应类型,比如Response或者自定义的JavaBean
      ... 
      responseConverter = createResponseConverter();   // 6. 根据上面获取的响应类型获取对应的Convert

      for (Annotation annotation : methodAnnotations) {  // 7. 解析第二步得到的方法注解
        parseMethodAnnotation(annotation);
      }
      ... 
      int parameterCount = parameterAnnotationsArray.length;
      parameterHandlers = new ParameterHandler<?>[parameterCount];
      for (int p = 0; p < parameterCount; p++) {
        Type parameterType = parameterTypes[p];
         ... 
        Annotation[] parameterAnnotations = parameterAnnotationsArray[p];   // 8. 解析第三步得到的参数注解
         ... 
        parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
      }

      return new ServiceMethod<>(this);  //  创建ServiceMethod对象
    }

之前有说过Retrofit中可以有多个ConvertFactory和CallAdapterFactory,通过上面的第4步和第6步获取该Method对应的ConvertFactory和CallAdapterFactory。这两种Factory的适配过程近乎一样,所以这里只做CallAdapterFactory的配对过程。

private CallAdapter<T, R> createCallAdapter() {
      Type returnType = method.getGenericReturnType();
      ... 
      Annotation[] annotations = method.getAnnotations();
      ...
      return (CallAdapter<T, R>) retrofit.callAdapter(returnType, annotations);
    }

Retrofit.class

public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType, Annotation[] annotations) {
                                                                // type: return 返回的类型,比如Call、Observable
     ...
    int start = adapterFactories.indexOf(skipPast) + 1;      // 用于做CallAdapterFactory跳过处理,默认start = 0
    for (int i = start, count = adapterFactories.size(); i < count; i++) {
      CallAdapter<?, ?> adapter = adapterFactories.get(i).get(returnType, annotations, this);
      if (adapter != null) {
        return adapter;
      }
    }
    ...
}

每一个CallAdapterFactory需要实现一个get(returnType,xxx)方法,如果能处理这个returnType就返回对应的CallAdapter对象。比如默认returnType为Call,那么就被默认的CallAdapterFactory接受处理,这个CallAdapterFactory在Android平台类中defaultCallAdapterFactory()获得(4.1 Retrofit创建过程 有说明)

Android.class

@Override CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
      if (callbackExecutor == null) throw new AssertionError();
      return new ExecutorCallAdapterFactory(callbackExecutor);
    }

ExecutorCallAdapterFactory.class

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) {
    if (getRawType(returnType) != Call.class) {
      return null;
    }
    final Type responseType = Utils.getCallResponseType(returnType);
    return new CallAdapter<Object, Call<?>>() {
      @Override public Type responseType() {
        return responseType;
      }

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

总结: ServiceMethod通过Builder模式创建,包含了Retrofit对象,对执行的Method进行剖析,像方法注解、参数注解、参数类型、CallAdapter、ConvertAdapter,所以一个ServiceMethod对象包含了网络请求需要的所有信息。

    1. 创建OkHttpCall对象

OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);

OkHttpCall.class

 OkHttpCall(ServiceMethod<T, ?> serviceMethod, @Nullable Object[] args) {
    this.serviceMethod = serviceMethod;
    this.args = args;
  }
  • 3 OkHttpCall通过CallAdapter进行Call的转化

serviceMethod.callAdapter.adapt(okHttpCall);

如果接口方法返回类型是Call的话,CallAdapter就是默认的CallAdaterFactory创建的CallAdapter,即ExecutorCallAdapterFactory类中get()方法返回的CallAdapter:

new CallAdapter<Object, Call<?>>() {
      @Override public Type responseType() {
        return responseType;
      }

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

接着定位返回的CallAdapter中adapt()方法,最后返回了一个new ExecutorCallbackCall<>(callbackExecutor, call); 对象,代表serviceMethod.callAdapter.adapt(okHttpCall);的执行结束,并向外暴露一个ExecutorCallbackCall对象。

    1. 同步异步网络请求
// 同步请求
call.execute();
// 异步请求
call.enqueue(new Callback<MyResponse>() {  //与OkHttp不同,异步请求会回调到主线程
            @Override
            public void onResponse(Call<MyResponse> call, Response<MyResponse> response) { }

            @Override
            public void onFailure(Call<MyResponse> call, Throwable t) { }
        });

与同步相比,异步相对来说复杂一点点,这里只分析异步,相信异步看懂了,同步肯定不在话下。

ExecutorCallbackCall.class

@Override public void enqueue(final Callback<T> callback) {
      ... 
      delegate.enqueue(new Callback<T>() {                 // delegate是由serviceMethod.callAdapter.adapt(okHttpCall); 传入的,所以最终的网络请求还是通过OkHttpCall进行。
        @Override public void onResponse(Call<T> call, final Response<T> response) {
          callbackExecutor.execute(new Runnable() {       // callbackExecutor 是Android平台对象类中的MainThreadExecutor 主要将线程切换到主线程
            @Override public void run() {
              if (delegate.isCanceled()) {
                 ...
              } 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);
            }
          });
        }
      });
    }

OkHttpCall.class

@Override public void enqueue(final Callback<T> callback) {
   ...
   call.enqueue(new okhttp3.Callback() {                    // 这个Call才是OKHttp中正宗的Call
      @Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse)
          throws IOException {
        Response<T> response;
        try {
          response = parseResponse(rawResponse);
        } catch (Throwable e) {
          callFailure(e);
          return;
        }
        callSuccess(response);
      }
   ... 
}

5. Retrofit设计模式

  • Builder模式
  • 外观模式
  • 静态工厂模式
  • 动态工厂模式
  • 适配器模式
  • 动态代理模式
    原文作者:负了时光不负卿
    原文地址: https://www.jianshu.com/p/7b1815e51956
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞