Retrofit源码分析

来源:互联网 发布:lol域名注册 编辑:程序博客网 时间:2024/05/23 01:11

———-继续,这篇分析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用到了很多种设计模式,这个我们得好好消化一下。完