Retrofit2源码解析(高工视角)

转载请注明出处:https://blog.csdn.net/m0_37840695/article/details/119773710

官网         Github地址

本文源码版本是2.3.0,是一个mavan项目,建议用IDEA打开。

1.官网介绍

 

 2.源码解析

 我们根据这段代码来看源码:

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

GitHubService service = retrofit.create(GitHubService.class);
Call<List<Repo>> reposCall = service.listRepos("octocat");
List<Repo> repos= reposCall.execute().body();//同步
reposCall.enqueue(new Callback<List<Contributor>>() {//异步
  @Override
  public void onResponse(Call<List<Repo>> call, Response<List<Repo>> response) {
        //回到了主线程
  }

  @Override
  public void onFailure(Call<List<Repo>> call, Throwable t) {
        //回到了主线程
  }
});

retrofit实例化

这个Platform类我们下文会分析。

这个BuiltInConverters基本不会用于生产中,也没啥营养,这里就不展示了。

addConverterFactory(GsonConverterFactory.create())

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

  通过java动态代理生成的代理类Proxy0:

public class Proxy0 extends Proxy implements GitHubService {

  //第一步, 生成构造器
  protected Proxy0(InvocationHandler h) {
    super(h);
  }

  //第二步, 生成静态域
  private static Method m1;  //hashCode方法
  private static Method m2;  //equals方法
  private static Method m3;  //toString方法
  private static Method m4;  //...
  
  //第三步, 生成代理方法
  @Override
  public int hashCode() {
    try {
      return (int) h.invoke(this, m1, null);
    } catch (Throwable e) {
      throw new UndeclaredThrowableException(e);
    }
  }
  
  @Override
  public boolean equals(Object obj) {
    try {
      Object[] args = new Object[] {obj};
      return (boolean) h.invoke(this, m2, args);
    } catch (Throwable e) {
      throw new UndeclaredThrowableException(e);
    }
  }
  
  @Override
  public String toString() {
    try {
      return (String) h.invoke(this, m3, null);
    } catch (Throwable e) {
      throw new UndeclaredThrowableException(e);
    }
  }
  
  @Override
  public List<Repo> listRepos(String user) {
    try {
      //构造参数数组, 如果有多个参数往后面添加就行了
      Object[] args = new Object[] {user};
      return (List<Repo>)h.invoke(this, m4, args);
    } catch (Throwable e) {
      throw new UndeclaredThrowableException(e);
    }
  }
  
  //第四步, 生成静态初始化方法
  static {
    try {
      Class c1 = Class.forName(Object.class.getName());
      Class c2 = Class.forName(GitHubService.class.getName());  
      m1 = c1.getMethod("hashCode", null);
      m2 = c1.getMethod("equals", new Class[]{Object.class});
      m3 = c1.getMethod("toString", null);
      m4 = c2.getMethod("save", new Class[]{GitHubService.class});
    
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
  
}

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

 这行代码将触发invocationHandler.invoke:

3.问题列表

3.1 retrofit是线程安全的吗?

3.2 我们发起网络请求是传入的CallBack会因为强引用而内存泄漏吗?

 所以是有可能引起内存泄漏的?错!

所以并不会导致内存泄漏 。

3.3 retrofit在运行时通过java的动态代理生成代理类,并解析被代理方法的注解生成serviceMethod,并将serviceMethod缓存,这种方式对比EventBus通过注解处理器在编译期解析注解并生成订阅点并保持到index(Java)文件中,两种方式孰优孰劣?

首先,我们该用第二种方式肯定也可以,而且只有优点没有缺点,具体参考我的EventBus源码解析。

其次,当前这种方式,有什么缺点吗?

通过java的动态代理生成代理类,只需要13ms左右(参考),性能很好。在invocationHandler.invoke方法中,解析被代理方法的注解生成serviceMethod,不存在CPU密集型操作,更不存在IO操作,是不耗时的:

 应该说当前方式性能也不差,我猜这也是为啥作者没有改用注解处理器的原因。

推荐:

OkHttp3源码解析

EventBus3源码解析


版权声明:本文为m0_37840695原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。