框架源码分析-retrofit

2016-11-16  本文已影响0人  twinsnan

使用

retrofit是最近一款比较火的第三方网络请求框架,使用注解、反射、代理模式等方式构造了整体的框架。
一、retrofit的使用
首先来看一下如何使用retrofit:
1、首先通过构造器模式创建了一个Builder对象,然后传入url地址,添加了Converter工厂,添加了RxJava的适配器工厂,通过build创建了一个Retrofit对象
2、通过retrofit对象,传入我们一个通过注解方式写的网络请求的接口,里面有我们写的网络请求的方法。然后返回一个Api的代理。retrofit通过代理模式,将注解后的内容解析成我们要网络请求传递的参数和数据,然后封装成一个请求的代理对象。
3、最后,调用代理对象的方法。由于retrofit可以非常完美的和Rxjava相结合,所以从下面的代码可以看出,api代理请求以后被在主线程中新建的Action1订阅,如果有数据,刷新列表。

这是RxJava的调用方式

 Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("http://www.google.com")
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .build();
        Api api = retrofit.create(Api.class);
        api.rxBenefits(20, count)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Action1<BaseModel<ArrayList<Benefit>>>() {
                    @Override
                    public void call(BaseModel<ArrayList<Benefit>> model) {
                                          
                    }
                }, new Action1<Throwable>() {
                    @Override
                    public void call(Throwable throwable) {
  
                    }
                })
        ;

这是普通的调用方式

 Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("http://www.google.com")
                .addConverterFactory(GsonConverterFactory.create())
                .build();
        Api api = retrofit.create(Api.class);
        Call<BaseModel<ArrayList<Benefit>>> call = api.defaultBenefits(20, count);
        call.enqueue(new Callback<BaseModel<ArrayList<Benefit>>>() {
                         @Override
                         public void onResponse(Call<BaseModel<ArrayList<Benefit>>> call, Response<BaseModel<ArrayList<Benefit>>> response) {
                                                }
                         @Override
                         public void onFailure(Call<BaseModel<ArrayList<Benefit>>> call, Throwable t) {
                     }
              }
        );
    }

retrofit主线分析

由于需要在创建Builder时传入平台的信息。所以先来看一下platform,如果在android平台,那么返回Android();如果在Java8平台,那么返回Java8(); 但是还有一个IOS?????????如果都不是,返回一个新的Platform对象。

  private static Platform findPlatform() {
    try {
      Class.forName("android.os.Build");
      if (Build.VERSION.SDK_INT != 0) {
        return new Android();
      }
    } catch (ClassNotFoundException ignored) {
    }
    try {
      Class.forName("java.util.Optional");
      return new Java8();
    } catch (ClassNotFoundException ignored) {
    }
    try {
      Class.forName("org.robovm.apple.foundation.NSObject");
      return new IOS();
    } catch (ClassNotFoundException ignored) {
    }
    return new Platform();
  }

看一下Plaform里面有什么,可以看到有Java8,Android,IOS内部类,这些内部类都是继承自Platform类的。


image.png

由于用在Android平台,所以我们只看Android中有些什么,有一个线程池内部内,运行在主线程上。可以获得一个defaultCallAdapterFactory,将线程池对象传了进去。这个等到以后会用到,先不分析这个,只要知道Platform可以拿到线程池和CallAdapterFactory。

static class Android extends Platform {
    @Override public Executor defaultCallbackExecutor() {
      return new MainThreadExecutor();
    }
    @Override CallAdapter.Factory defaultCallAdapterFactory(Executor callbackExecutor) {
      return new ExecutorCallAdapterFactory(callbackExecutor);
    }
    static class MainThreadExecutor implements Executor {
      private final Handler handler = new Handler(Looper.getMainLooper());
      @Override public void execute(Runnable r) {
        handler.post(r);
      }
    }
  }

这个分析完以后,我们来看retrofit的建造者内部类。

  public static final class Builder {
    // 上面分析的Platform
    private Platform platform;
    // 目前只支持okhttp,获取okhttp的工厂类
    private okhttp3.Call.Factory callFactory;
    // 我们设置的Url
    private HttpUrl baseUrl;
    // 一个converterFactory的List,主要用于将请求内容转化
    private List<Converter.Factory> converterFactories = new ArrayList<>();
    // 用于包装call的工厂的list
    private List<CallAdapter.Factory> adapterFactories = new ArrayList<>();
    // 我们穿进去的线程池
    private Executor callbackExecutor;
    // 不知道。。。
    private boolean validateEagerly;
    Builder(Platform platform) {
    // 创建Builder时,需要传入平台的信息
      this.platform = platform;
      // Add the built-in converter factory first. This prevents overriding its behavior but also
      // ensures correct behavior when using converters that consume all types.
    // 添加一个内置的converter的工厂
      converterFactories.add(new BuiltInConverters());
    }
    public Builder() {
      this(Platform.get());
    }
 
    public Builder client(OkHttpClient client) {
      return callFactory(checkNotNull(client, "client == null"));
    }

    public Builder callFactory(okhttp3.Call.Factory factory) {
      this.callFactory = checkNotNull(factory, "factory == null");
      return this;
    }

    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);
    }
       public Builder baseUrl(HttpUrl baseUrl) {
      checkNotNull(baseUrl, "baseUrl == null");
      List<String> pathSegments = baseUrl.pathSegments();
      if (!"".equals(pathSegments.get(pathSegments.size() - 1))) {
        throw new IllegalArgumentException("baseUrl must end in /: " + baseUrl);
      }
      this.baseUrl = baseUrl;
      return this;
    }
    /** Add converter factory for serialization and deserialization of objects. */
    public Builder addConverterFactory(Converter.Factory factory) {
      converterFactories.add(checkNotNull(factory, "factory == null"));
      return this;
    }

    public Builder addCallAdapterFactory(CallAdapter.Factory factory) {
      adapterFactories.add(checkNotNull(factory, "factory == null"));
      return this;
    }

    public Builder callbackExecutor(Executor executor) {
      this.callbackExecutor = checkNotNull(executor, "executor == null");
      return this;
    }
   
    public Builder validateEagerly(boolean validateEagerly) {
      this.validateEagerly = validateEagerly;
      return this;
    }
    
    public Retrofit build() {
    // 判断url是否为空
      if (baseUrl == null) {
        throw new IllegalStateException("Base URL required.");
      }
    // 看是否有传入一个callFactory,如果没有传入,那么就创建一个新的
      okhttp3.Call.Factory callFactory = this.callFactory;
      if (callFactory == null) {
        callFactory = new OkHttpClient();
      }
    // 看是否有传入线程池,如果没有传入,创建一个新的,这里看到我们上满分析的Platform类,创建一个运行在主线程的callbackExecutor
      Executor callbackExecutor = this.callbackExecutor;
      if (callbackExecutor == null) {
        callbackExecutor = platform.defaultCallbackExecutor();
      }
    // 新建calladapter的List,添加platform中默认的factory,这个factory也是我们上面分析到过的,但是具体功能等到下面来分析。主要用于将请求适配成我们需要的Call请求封装对象
      // Make a defensive copy of the adapters and add the default Call adapter.
      List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
      adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
    // 将构造器中的convertfactory List放进去,这个主要用于将请求转换为我们需要的格式

      // Make a defensive copy of the converters.
      List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);
    // 创建retrofit对象返回
      return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
          callbackExecutor, validateEagerly);
    }
  }

分析完构造器,我们再来看一下通过代理模式创建请求接口的对象的代码。源码注释中已经写得比较明白了这个方法的具体作用

  @SuppressWarnings("unchecked") // Single-interface proxy creation guarded by parameter safety.
  public <T> T create(final Class<T> service) {
    // 首先接茬service是否为一个符合规范的interface,如果不是接口,或者实现了其他接口,则抛出异常
    Utils.validateServiceInterface(service);
    if (validateEagerly) {
      eagerlyValidateMethods(service);
    }
    // 动态代理,这个retrofit比较关键的部分
    return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
        new InvocationHandler() {
    // 获取Platform对象
          private final Platform platform = Platform.get();
          @Override public Object invoke(Object proxy, Method method, Object... args)
              throws Throwable {
            // If the method is a method from Object then defer to normal invocation.
    // 得到目标方法所在类对应的Class对象,如果是Object类,则调用一般的反射
            if (method.getDeclaringClass() == Object.class) {
              return method.invoke(this, args);
            }
    // 在Android凭条,这个都是false
            if (platform.isDefaultMethod(method)) {
              return platform.invokeDefaultMethod(method, service, proxy, args);
            }
    // 通过反射获得ServiceMethod对象
            ServiceMethod serviceMethod = loadServiceMethod(method);
    // 获得一个OkHttpCall
            OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
    // 调用CallAdapter中的adapt方法,将okHttpCall转换为我们需要的类型
            return serviceMethod.callAdapter.adapt(okHttpCall);
          }
        });
  }

接下来我们对上面三个标黄的方法逐个分析
首先来卡ServiceMethod类,下面这个是Retrofit中的方法。

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

serviceMethodCache是一个非常重要的map,用于保存代理后的方法。
loadServiceMethod也是Retrofit中的方法,首先判断是否已经存在,如果不存在则创建,创建后加入到map中。

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

分析new ServiceMethod.Builder(this, method).build();
在ServiceMethod类中:

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

(注:getgenericparametertypes)

public type[] getgenericparametertypes()
按照声明顺序返回 type 对象的数组,这些对象描述了此 method 对象所表示的方法的形参类型的。如果底层方法不带参数,则返回长度为 0 的数组。
如果形参类型是参数化类型,则为其返回的 type 对象必须实际反映源代码中使用的实际类型参数。
如果形参类型是类型变量或参数化类型,则创建它。否则将解析它。
返回:
按照声明顺序返回表示底层方法的形参类型的 type 对象数组

建造者构建

    public ServiceMethod build() {
    // 新建callAdapter
      callAdapter = createCallAdapter();
    // ...
      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
      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);
    }
    private CallAdapter<?> 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 {
        return 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);
      }
    }

callAdapter中调用的是Retrofit中的代码

  /**
   * Returns the {@link CallAdapter} for {@code returnType} from the available {@linkplain
   * #callAdapterFactories() factories} except {@code skipPast}.
   *
   * @throws IllegalArgumentException if no call adapter available for {@code type}.
   */
  public CallAdapter<?> nextCallAdapter(CallAdapter.Factory skipPast, Type returnType,
      Annotation[] annotations) {
    checkNotNull(returnType, "returnType == null");
    checkNotNull(annotations, "annotations == null");
    int start = adapterFactories.indexOf(skipPast) + 1;
    for (int i = start, count = adapterFactories.size(); i < count; i++) {
      CallAdapter<?> adapter = adapterFactories.get(i).get(returnType, annotations, this);
      if (adapter != null) {
        return adapter;
      }
    }

如果是默认的,则调用ExecutorCallAdapterFactory中的get方法,返回的Call最主要的是adapt。adapt方法将一个Call对象传入。我们来看一下传入后返回的是什么
记得创建Retrofit对象时如果不传入CallAdaperFactory,那么会新建ExecutorCallAdapterFactory,新建时将主线程的Executor传入。adapt后的ExecutorCallbackCall中enqueue非常重要,其将在子线程中请求的返回值发布到主线程中,然后是success和fail的方法回调。

@Override
  public CallAdapter<Call<?>> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
    if (getRawType(returnType) != Call.class) {
      return null;
    }
    final Type responseType = Utils.getCallResponseType(returnType);
    return new CallAdapter<Call<?>>() {
      @Override public Type responseType() {
        return responseType;
      }
      @Override public <R> Call<R> adapt(Call<R> 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) {
      if (callback == null) throw new NullPointerException("callback == null");
      delegate.enqueue(new Callback<T>() {
        @Override public void onResponse(final 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(call, new IOException("Canceled"));
              } else {
                callback.onResponse(call, response);
              }
            }
          });
        }
        @Override public void onFailure(final Call<T> call, final Throwable t) {
          callbackExecutor.execute(new Runnable() {
            @Override public void run() {
              callback.onFailure(call, t);
            }
          });
        }
      });
    }

最后我们来看一下请求前和请求后对数据进行封装和解析的过程。
在Retrofit进行创建的时候,我们是可以传入一个ConvertorFactory对象的,如最上面的示例。

Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("http://gank.io/")
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .build();

那么我们来看一下GsonConverterFactory里面有什么

/**
 * A {@linkplain Converter.Factory converter} which uses Gson for JSON.
 * <p>
 * Because Gson is so flexible in the types it supports, this converter assumes that it can handle
 * all types. If you are mixing JSON serialization with something else (such as protocol buffers),
 * you must {@linkplain Retrofit.Builder#addConverterFactory(Converter.Factory) add this instance}
 * last to allow the other converters a chance to see their types.
 */
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.
   */
  public static GsonConverterFactory create(Gson gson) {
    return new GsonConverterFactory(gson);
  }
  private final Gson gson;
  private GsonConverterFactory(Gson gson) {
    if (gson == null) throw new NullPointerException("gson == null");
    this.gson = gson;
  }
  @Override
  public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
      Retrofit retrofit) {
    TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
    return new GsonResponseBodyConverter<>(gson, adapter);
  }
  @Override
  public Converter<?, RequestBody> requestBodyConverter(Type type,
      Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
    TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
    return new GsonRequestBodyConverter<>(gson, adapter);
  }
}

从源码中可以看到,该类继承自 Converter.Factory,最主要的是responseBodyConverter和requestBodyConverter这两个方法。这两个方法获得请求和相应的转换类,再进去看下转换类里面的内容。发现是一些Gson转换的东西。

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 {
      return adapter.read(jsonReader);
    } finally {
      value.close();
    }
  }
}

在ServiceMethod创建时获得了ResponseConverter,该Conveter是从retrofit中获得的

responseConverter = createResponseConverter();

在ServiceMethod的toResponse方法中使用了responseConveter.convert方法。(toResponse方法在OkHttpCall执行请求结束后的parseResponse中调用)

  /** Builds a method return value from an HTTP response body. */
  T toResponse(ResponseBody body) throws IOException {
    return responseConverter.convert(body);
  }

而requestConverter方法则在ServiceMethod中的parseParameterAnnotation方法中调用,获取了retrofit中的Converter对象。

 Converter<?, RequestBody> converter =
                retrofit.requestBodyConverter(iterableType, annotations, methodAnnotations);

到这里,Retrofit的大致框架已经分析完了。如果有机会,RxjavaCallAdapter这个比较重要的部分还没有分析,会再去详细的分析。

源码

github上的源码:
https://github.com/square/retrofit

上一篇下一篇

猜你喜欢

热点阅读