Retrofit 源码分析

简介:retrofit一直是我从来没有考虑过使用的一款网络框架,理由是 嫉妒。


1.retrofit实际上就是对okhttp3的封装,并没有什么特殊的,或者说是提高性能的技术,

只是通过注解的方式,让我们的应用扩展起来更加方便,但是由于我的个人习惯都是自己做一个类似retrofit这一层的接口层,所以在接触到retrofit的时候,第一感觉就是我的活被人抢了,


首先说一下,retrofit所实现的几个部分:

1.对请求网络的封装

2.对返回数据的封装

3.对OkhttpClient的封装。


首先,使用okhttp3的话,需要自己封装自己的url,但是使用retrofit只需要使用下面这种形式,就会在请求网络的时候,自动拼接成url,确实比较简单。

public interface GitHub {
    @GET("/repos/{owner}/{repo}/contributors")
    Call> contributors(
            @Path("owner") String owner,
            @Path("repo") String repo);
}
返回数据的封装,同样是在上面定义的,
public static class Contributor {
    public final String login;
    public final int contributions;

    public Contributor(String login, int contributions) {
        this.login = login;
        this.contributions = contributions;
    }
}
将返回的json直接解析成Contributor对象,省略了我们解析的过程,
使用起来也很方便
public static final String API_URL = "https://api.github.com";
Retrofit retrofit = new Retrofit.Builder()
        .baseUrl(API_URL)
        .addConverterFactory(GsonConverterFactory.create())
        .build();

// Create an instance of our GitHub API interface.
GitHub github = retrofit.create(GitHub.class);

// Create a call instance for looking up Retrofit contributors.
Call> call = github.contributors("square", "retrofit");

// Fetch and print a list of the contributors to the library.
List contributors = null;
try {
    contributors = call.execute().body();
} catch (IOException e) {
    e.printStackTrace();
}
简直就是无脑操作,感觉这个根本就不是网络请求数据,完全就是我们平时写的逻辑代码,没有任何的json格式痕迹,

整体略有设计优化的地方是
GitHub github = retrofit.create(GitHub.class);
这里的原理是通过java的proxy原理,hook住接口的方法,当调用GitHub子类的时候,我们就可以记录下方法与当前环境的匹配关系,然后,下次的时候,就不需要再次创建了,详细代码如下:
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 serviceMethod =
              (ServiceMethod) loadServiceMethod(method);
          OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
          return serviceMethod.callAdapter.adapt(okHttpCall);
        }
      });
}
  
  
    
    
    
    
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;
}
看到这里,你可能会有好奇,并没有看到OkhttpClient啊,
其实在build的时候,如果我们没有设置,就会默认设置的
public Retrofit build() {
  if (baseUrl == null) {
    throw new IllegalStateException("Base URL required.");
  }

  okhttp3.Call.Factory callFactory = this.callFactory;
  if (callFactory == null) {
    callFactory = new OkHttpClient();    //绑定OkhttpClient,以后都会调用他,
  }

  Executor callbackExecutor = this.callbackExecutor;
  if (callbackExecutor == null) {
    callbackExecutor = platform.defaultCallbackExecutor();
  }

  // Make a defensive copy of the adapters and add the default Call adapter.
  List adapterFactories = new ArrayList<>(this.adapterFactories);
  adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));

  // Make a defensive copy of the converters.
  List converterFactories = new ArrayList<>(this.converterFactories);

  return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
      callbackExecutor, validateEagerly);
}
看到这里之后,整体设计思路都清晰了,其实就是在OkHttp3的基础之上,使用代理模式,结构图如下:

Retrofit 源码分析_第1张图片


到目前为止,retrofit整体介绍完成了,
下面说一下我长使用的一种封装模式:

1.对请求网络的封装   =>   通过fastjson解析,将对象按照我们需要的格式解析,然后封装为url,没有采用注解方式,效率更高,

2.对返回数据的封装   =>   返回的数据,同样是通过fastjson,解析成我们提前泛好的对象,

3.对OkhttpClient的封装。   =>   可以对任何的网络对象进行封装,


综上所述,我们自己所实现的方式,与retrofit在使用的时候,便利性来说是一致的,但是我没有采用retrofit的方式原因如下:

1.retrofit与okhttp绑定比较紧(当然我们也可以把retrofit的注释解析这一套解析出来,适用其他网络框架),由于技术更新较快,所以如果以后出现其他网络框架的话,替换比较麻烦,

2.retrofit采用的反射与hook方式,所以性能可能会略有影响,

3.我看到retrofit并没有让我看到眼前一亮的感觉,整体并没有特别大的优势。


综上几个原因:我们仍然采用自己的网络框架,来实现网络功能。





你可能感兴趣的:(Retrofit 源码分析)