Android-Retrofit源码解析(一)调用流程(上)

我们知道,Retrofi的底层实际上是用OkHttp来进行网络请求的,本文也将会详细分析到OkHttp里面的调用链。

Retrofit基本用法

直接看官网https://square.github.io/retrofit/的例子。
首先创建一个GitHubService接口,这个接口定义了所有的网络请求。Repo是一个bean类,你可以在里面只定义一个String name;的变量。

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

然后在我们的自己的类中,创建一个Retrofit对象,并调用Retrofit.create方法创建GitHubService的实例。

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

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

接下来调用GitHubService的方法,得到Call对象的实例。通过这个Call的实例可以发起同步或者异步请求。

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

发起异步请求。

repos.enqueue(new Callback<List<Repo>>() {
   @Override
    public void onResponse(Call<List<Repo>> call, Response<List<Repo>> response) {
              Log.d("MainActivity", response.toString());
    }

   @Override
    public void onFailure(Call<List<Repo>> call, Throwable t) {
             Log.d("MainActivity", t.toString());
    }
});

调用流程源码解析

1. 创建Retrofit对象的实例
Retrofit实例创建使用了Builder模式。Builder的代码比较简单。主要看一下其构造函数。

    Builder(Platform platform) {
      this.platform = platform;//Retrofit既可以用于Android端,也可以用于Java平台。platform指的就是这两个平台。
    }
    
    public Builder() {
      this(Platform.get());
    }

    Builder(Retrofit retrofit) {
      platform = Platform.get();
      callFactory = retrofit.callFactory;//Call对象的创建工厂。
      baseUrl = retrofit.baseUrl;//一般是域名

      // Do not add the default BuiltIntConverters and platform-aware converters added by build().
      for (int i = 1,
          size = retrofit.converterFactories.size() - platform.defaultConverterFactoriesSize();
          i < size; i++) {
        converterFactories.add(retrofit.converterFactories.get(i));//变换器Converter列表。
      }

      // Do not add the default, platform-aware call adapters added by build().
      for (int i = 0,
          size = retrofit.callAdapterFactories.size() - platform.defaultCallAdapterFactoriesSize();
          i < size; i++) {
        callAdapterFactories.add(retrofit.callAdapterFactories.get(i));//调用Service的方法返回的是Call对象如果不想要Call对象,例如与RxJava一起使用时,想要返回的是一个Observable对象,就通过传入一个RxJava的CallAdapter来实现。
      }

      callbackExecutor = retrofit.callbackExecutor;//调用Service方法后的回调。
      validateEagerly = retrofit.validateEagerly;
    }

2. Retrofit#create()方法

  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();
          private final Object[] emptyArgs = new Object[0];

          @Override public Object invoke(Object proxy, Method method, @Nullable 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);
            }
            return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
          }
        });
  }

Retrofit#create()方法创建了一个GitHubService的代理类。

3. 调用GitHubService中的接口方法
调用GitHubService中的接口方法,其实执行的是代理类的invoke方法,也就是上面代码中InvocationHandler中override的invoke方法。我们先看一下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 = ServiceMethod.parseAnnotations(this, method);
        serviceMethodCache.put(method, result);
      }
    }
    return result;
  }

这个方法返回了一个ServiceMethod对象。ServiceMethod是一个抽象类。调用ServiceMethod.parseAnnotations得到真正的实现类HttpServiceMethod。

  static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
    RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);

    Type returnType = method.getGenericReturnType();
    if (Utils.hasUnresolvableType(returnType)) {
      throw methodError(method,
          "Method return type must not include a type variable or wildcard: %s", returnType);
    }
    if (returnType == void.class) {
      throw methodError(method, "Service methods cannot return void.");
    }

    return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
  }

实际执行HttpServiceMethod.parseAnnotations。这个parseAnnotations方法先通过CallAdapter拿到调用GitHubService要返回的类型,然后创建一个转换器Converter,将返回的数据流转换成目标类型。

  static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
      Retrofit retrofit, Method method, RequestFactory requestFactory) {
    CallAdapter<ResponseT, ReturnT> callAdapter = createCallAdapter(retrofit, method);
    Type responseType = callAdapter.responseType();
    if (responseType == Response.class || responseType == okhttp3.Response.class) {
      throw methodError(method, "'"
          + Utils.getRawType(responseType).getName()
          + "' is not a valid response body type. Did you mean ResponseBody?");
    }
    if (requestFactory.httpMethod.equals("HEAD") && !Void.class.equals(responseType)) {
      throw methodError(method, "HEAD method must use Void as response type.");
    }

    Converter<ResponseBody, ResponseT> responseConverter =
        createResponseConverter(retrofit, method, responseType);

    okhttp3.Call.Factory callFactory = retrofit.callFactory;
    return new HttpServiceMethod<>(requestFactory, callFactory, callAdapter, responseConverter);
  }

loadServiceMethod(method)方法拿到HttpServiceMethod的实例之后,就会执行其invoke方法。

 @Override ReturnT invoke(Object[] args) {
    return callAdapter.adapt(
        new OkHttpCall<>(requestFactory, args, callFactory, responseConverter));
  }

Android7.0(Android SDK>=24)以上包括7.0,默认有两个CallAdapterFactory,一个是CompletableFutureCallAdapterFactory,一个是ExecutorCallAdapterFactory。Android7.0以下,只有一个ExecutorCallAdapterFactory。到底调用哪个CallAdapterFactory是根据我们在GitHubService中定义的方法的返回类型来确定的。
也就说,通过调用GitHubService接口的方法,一步一步到这里,调用的是ExecutorCallAdapterFactory/CompletableFutureCallAdapterFactory中生成的CallAdapter的adapt方法。
这里调用的是ExecutorCallAdapterFactory的adapt方法。

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

ExecutorCallAdapterFactory的adapt方法new 了一个ExecutorCallbackCall对象,直接return了。这个ExecutorCallbackCall实现了Call接口。后面我们执行call.enqueue操作时,实际就是执行的ExecutorCallbackCall里的enqueue方法。

整个前面这部分的思路可以说已经清晰了,简单总结一下:
调用Retrofit的create方法创建了我们定义请求的代理类,调用请求方法则是执行了CallAdapter的adapt方法,至于调用哪个CallAdapterFactory是根据定义请求接口的返回类型来选择的。默认会返回一个ExecutorCallbackCall对象。利用这个对象,我们可以发起同步或者异步请求。

由于篇幅太长,怕影响到阅读,后面发起请求部分的分析将放到下一篇来讲。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值