简介: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简直就是无脑操作,感觉这个根本就不是网络请求数据,完全就是我们平时写的逻辑代码,没有任何的json格式痕迹,> 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(); }
整体略有设计优化的地方是
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, ?> 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看到这里之后,整体设计思路都清晰了,其实就是在OkHttp3的基础之上,使用代理模式,结构图如下: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); }
到目前为止,retrofit整体介绍完成了,
下面说一下我长使用的一种封装模式:
1.对请求网络的封装 => 通过fastjson解析,将对象按照我们需要的格式解析,然后封装为url,没有采用注解方式,效率更高,
2.对返回数据的封装 => 返回的数据,同样是通过fastjson,解析成我们提前泛好的对象,
3.对OkhttpClient的封装。 => 可以对任何的网络对象进行封装,
综上所述,我们自己所实现的方式,与retrofit在使用的时候,便利性来说是一致的,但是我没有采用retrofit的方式原因如下:
1.retrofit与okhttp绑定比较紧(当然我们也可以把retrofit的注释解析这一套解析出来,适用其他网络框架),由于技术更新较快,所以如果以后出现其他网络框架的话,替换比较麻烦,
2.retrofit采用的反射与hook方式,所以性能可能会略有影响,
3.我看到retrofit并没有让我看到眼前一亮的感觉,整体并没有特别大的优势。
综上几个原因:我们仍然采用自己的网络框架,来实现网络功能。