Retrofit 源码分析

来源:互联网 发布:查淘宝宝贝隐形降权 编辑:程序博客网 时间:2024/05/22 15:46

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


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

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


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

1.对请求网络的封装

2.对返回数据的封装

3.对OkhttpClient的封装。


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

public interface GitHub {    @GET("/repos/{owner}/{repo}/contributors")    Call<List<Contributor>> 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<List<Contributor>> call = github.contributors("square", "retrofit");// Fetch and print a list of the contributors to the library.List<Contributor> 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<Object, Object> serviceMethod =              (ServiceMethod<Object, Object>) loadServiceMethod(method);          OkHttpCall<Object> 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<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);  adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));  // Make a defensive copy of the converters.  List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);  return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,      callbackExecutor, validateEagerly);}
看到这里之后,整体设计思路都清晰了,其实就是在OkHttp3的基础之上,使用代理模式,结构图如下:


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

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

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

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


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

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

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

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


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





0 0
原创粉丝点击