从Retrofit的原理来看HTTP

Retrofit使用方法简介

  1. 创建一个interface作为Web Service的请求集合,在里面用注解(Annotation)写入需要配置的请求方法

    1
    2
    3
    4
    public interface GitHubService{
    @GET("users/{user}/repos")
    Call<List<Repo>> listRepos(@Path("user") String user);
    }
  2. 在正式代码里用Retrofit创建出interface的实例

    1
    2
    3
    4
    Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("https://api.github.com/")
    .build();
    GitHubService service = retrofit.create(GitHubService.class);
  3. 调用创建出的Service实例的对应方法,创建出相应的可以用来发起网络请求的Call对象

    1
    Call<List<Repo>> repos = service.listRepos("octocat");
  4. 使用Call.execute()或者Call.enqueue()来发起请求

    1
    repos.enqueue(callback);

Retrofit源码结构总结

  • 通过Retrofit.create(Class)方法创建出Service interface的实例,从而使得Service中配置的方法变得可用,这是Retrofit代码结构的核心

  • Retrofit.create()方法内部,使用的是Proxy.newProxyInstance()方法来创建Service实例。这个方法会为参数中的多个interface(具体到Retrofit来说,是固定传入一个interface)创建一个对象,这个对象实现了所有interface的每个方法,并且每个方法的实现都是雷同的:调用对象实例内部的一个InvocationHandler成员变量的invoke()方法,并把自己的方法信息传递进去。这样就在实质上实现了代理逻辑:interface中的方法全部由另一个设定的InvocationHandler对象来进行代理操作。并且,这些方法的具体实现是在运行时生成interface实例时才确定的,而不是在编译时(虽然在编译时就已经可用通过代码逻辑推断出来)。这就是网上所说的“动态代理机制”的具体含义。

  • 因此,invoke()方法中的逻辑,就是Retrofit创建Service实例的关键。这个方法内有三行关键代码,共同组成了具体逻辑:

    1. ServiceMethod的创建:

      1
      loadServiceMethod(method)

      这行代码负责读取interface中原方法的信息(包括返回值类型、方法注解、参数类型、参数 注解),并将这些信息做初步分析。实际返回的是一个CallAdapted

    2. OkHttpCall的创建:

      1
      new OkHttpCall<>(requestFactory, args, callFactory, responseConverter)

      OkHttpCallretrofit2.Call的子类。这行代码负责将ServiceMethod解读到的信息(主要是一个)