Retrofit源码分析

———-继续,这篇分析Retrofit的源码。(真是太懒了)
首先看一下官网的介绍,(官网 在此),官网给的描述是 A type-safe HTTP client for Android and Java,其实也就是对okhttp再次进行了封装,使得开发者更方便的使用网络请求。基本使用如下:
1,先创建一个接口,里面定义了请求方式,地址,返回数据类型,参数。

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

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

2,生成一个Retrofit实例,然后调用create()方法,传入刚才创建的GitHubService 类名。

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

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

3,直接从接口拿到一个Call,当然,这个类型可以是其他类型的。

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

基本用法请自行了解,这里我们主要分析源码。


创建Retrofit 实例是一个Builder模式,没什么好说的,需要注意的一点是, 这创建的时间调用了unmodifiableList(),这是Collections类的一个方法,

public static <T> List<T> unmodifiableList(List<? extends T> list) {
        return (list instanceof RandomAccess ?
                new UnmodifiableRandomAccessList<>(list) :
                new UnmodifiableList<>(list));
    }

瞄一眼方法描述,Returns an unmodifiable view of the specified list. This method allows modules to provide users with “read-only” access to internal lists. 开头两句是这么写的, 就是说返回一个不可更改的List对象,可以保护创建的对象中的数据只读, 不能更改。之前没遇到过,记录下。

接下来重点(敲黑板!!!

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, 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<Object, Object> serviceMethod =
                (ServiceMethod<Object, Object>) loadServiceMethod(method);
            OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
            return serviceMethod.callAdapter.adapt(okHttpCall);
          }
        });
  }

看到了一个返回Proxy,知道这是代理的意思,其实这里用到了动态代理的方法,(有关 动态代理和静态代理的 区别请看 )。
这里解释下InvocationHandler 中回调invoke方法的参数 。

  1. Object proxy: 代理对象,不关心这个
  2. Method method:调用的方法,就是listRepos方法
  3. Object… args:方法的参数,就是”octocat”
    可以知道,
 if (method.getDeclaringClass() == Object.class) {
              return method.invoke(this, args);
 }
if (platform.isDefaultMethod(method)) {
              return platform.invokeDefaultMethod(method, service, proxy, args);
 }

都不会执行。
那么接下来我们首先看 loadServiceMethod(method) 方法 。

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

这里有Map去缓存ServiceMethod对象,如果有则直接返回,没有就去创建 。

我们看ServiceMethod的构造函数。也是使用了Builder模式 ,

    public ServiceMethod build() {
      callAdapter = createCallAdapter();
      responseType = callAdapter.responseType();
      responseConverter = createResponseConverter();
      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);
      }
      return new ServiceMethod<>(this);
    }

这里删除一些检查的代码,看主要的。
最后调用build();会创建一些初始对象。每一个参数都都会封装到一个ParameterHandler里。
然后new 了一个okhttpCall ,直接调用 serviceMethod.callAdapter.adapt(okHttpCall); 这里的serviceMethod.callAdapte , 就是之前serviceMethod.Builder 中调用createCallAdapter()返回赋值给serviceMethod的成员对象。
这里比较有意思了,

 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
        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.callAdapter ,返回到了Retrofit中, 在nextCallAdapter 中有

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

遍历adapterFactories,依据刚才在GitHubService 中每个方法的返回值,对应着一个Factory,比如,在Retrofit中Builder的时候默认添加了一个

 adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));

,也就是说当你在初始化Retrofit的时候不去addCallAdapterFactory();默认的返回类型必须是Call。返回其它的类型,在遍历的时候找不到对应的Factory, 会抛异常。

回到serviceMethod.callAdapter.adapt(okHttpCall);

这里的callAdapter 其实默认就是一个ExecutorCallAdapterFactory.get()返回的值 , 我们进入这个类。

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

看Call方法

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

当我们拿到一个Call 时, 可以去enqueue()(异步),或execute();那么这个Call呢, 其实就是OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);这里的Call了。OkHttpCall我觉得可以当作是适配器模式,可也以做包装设计模式 。
这里面的代码比较简单,直接生成一个Okhttp包的Call,再去调用。


至此,Retrofit 的源码已经分析完,我们只是粗略的过了一下流程,整个Retrofit用到了很多种设计模式,这个我们得好好消化一下。完

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值