背景
- Retrofit是Square公司开发的一款针对Android网络请求的框架,Retrofit2底层基于OkHttp实现的。
- 官方对它的解释是:A type-safe HTTP client for Android and Java ,就是一个安全的可用于Android和java的网络库。
- 它可以简化我们操作网络的成本,其实所有第三方库的功能,我们用原生的api都是可以实现的,只不过需要花费时间和精力,且在某些场景下可能出现bug和性能不太好,而第三方开源库已经有很多产品使用,得到了验证和完善,所以我们推荐使用第三方库,不过我们需要对开源库的实现原理了解,这样在出现问题的时候能方便的排查问题。
Rest API
- 这里简单说下什么是Rest API。 REST是一种架构风格,用于创建Web服务,几乎总是工作在HTTP上。它的工作原理几乎以同样的方式得到的网页,也有标准的方法来创建,更新和删除。
例子
首先可以定义一个interface,代码如下所示:
12345public interface APIService {"News")(Call<ResponseBody> getNews(@Query("limit") String limit);}可以定义一个ServiceManager,里面用来初始化Retrofit,代码如下:
|
|
- 接下来定义一个NewsInfo实体类,实体类的字段是和json对应的,代码如下:
|
|
- 最后就是使用,非常简洁,代码如下:12345678910111213APIService service = retrofit.create(APIService.class);Call<NewsInfo> call = service.getNews("10");call.enqueue(new Callback<NewsInfo>() {public void onResponse(Call<NewsInfo> call,Response<NewsInfo> response) {Log.i(TAG, "onResponse");}public void onFailure(Call<NewsInfo> call, Throwable t) {Log.i(TAG, "onFailure");}});
代码分析
|
|
- 这使用到了常见的构造者模式,我们来看builder()做了什么:
|
|
再看baseUrl()的代码:
123456789101112131415161718// 通过下面的代码,可以看出其实它拿到baseUrl主要创建了okhttp的HttpUrl。public Builder baseUrl(String baseUrl) {checkNotNull(baseUrl, "baseUrl == null");HttpUrl httpUrl = HttpUrl.parse(baseUrl);if (httpUrl == null) {throw new IllegalArgumentException("Illegal URL: " + baseUrl);}return baseUrl(httpUrl);}public Builder baseUrl(HttpUrl baseUrl) {checkNotNull(baseUrl, "baseUrl == null");List<String> pathSegments = baseUrl.pathSegments();if (!"".equals(pathSegments.get(pathSegments.size() - 1))) {throw new IllegalArgumentException("baseUrl must end in /: " + baseUrl);}this.baseUrl = baseUrl;return this;}再看addConverterFactory(GsonConverterFactory.create()):
12345// 往转换工厂集合中添加了我们指定的转换工厂.在我们的例子里面 GsonConverterFactory 将选用 GsonConverter 来转换。public Builder addConverterFactory(Converter.Factory factory) {converterFactories.add(checkNotNull(factory, "factory == null"));return this;}接下来是build的过程:
12345678910111213141516171819202122232425public Retrofit build() {if (baseUrl == null) {throw new IllegalStateException("Base URL required.");}okhttp3.Call.Factory callFactory = this.callFactory;if (callFactory == null) {callFactory = new 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);}// 这就是创建Retorfit对象的地方,将前面几步配置的参数都设置到Retrofit中,这里可以很明确的看到默认callFactory用的是OKHttpClient
创建接口实例并调用
对应上面的代码:
12APIService service = retrofit.create(APIService.class);Call<NewsInfo> call = service.getNews("10");我们先看一下create的代码,它主要做了什么我都写到注释中:
1234567891011121314151617181920212223242526272829303132333435363738public <T> T create(final Class<T> service) {// 检查service是否是个接口Utils.validateServiceInterface(service);// 检查是否要提前创建serviceMethodif (validateEagerly) {eagerlyValidateMethods(service);}// 这里就是设计非常巧妙的地方了,用到了java动态代理,我会在另外一篇文章中讲动态代理// 这里返回的是一个动态代理,然后又转成了对应的接口类型return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },new InvocationHandler() {private final Platform platform = Platform.get();public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {// If the method is a method from Object then defer to normal invocation.// 判断是会否为object方法,是的话就直接调用if (method.getDeclaringClass() == Object.class) {return method.invoke(this, args);}// 这里现在默认是直接返回false的。if (platform.isDefaultMethod(method)) {return platform.invokeDefaultMethod(method, service, proxy, args);}// 接下来主要做了以下事情:// 1. 去serviceMethodCache,查是否有对应serviceMethod的缓存。执行完一遍会缓存下来。// 2. 如果不存在缓存就去创建一个,所以下面我们重点分析创建build的过程。//ServiceMethod<Object, Object> serviceMethod =(ServiceMethod<Object, Object>) loadServiceMethod(method);OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);return serviceMethod.callAdapter.adapt(okHttpCall);}});}接下来我们看下ServiceMethod的build过程:
|
|
- 接下来就是创建一个OKHttpCall
|
|
- 接下来就是返回处理
|
|
发起请求
上一步提到,当执行定义的service方法,本例中是getNews,会返回一个ExecutorCallbackCall,我们接下来看下这个类的结构:
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061static final class ExecutorCallbackCall<T> implements Call<T> {final Executor callbackExecutor;final Call<T> delegate;ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {this.callbackExecutor = callbackExecutor;this.delegate = delegate;}public void enqueue(final Callback<T> callback) {if (callback == null) throw new NullPointerException("callback == null");delegate.enqueue(new Callback<T>() {public void onResponse(Call<T> call, final Response<T> response) {callbackExecutor.execute(new Runnable() {public void run() {if (delegate.isCanceled()) {// Emulate OkHttp's behavior of throwing/delivering an IOException on cancellation.callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled"));} else {callback.onResponse(ExecutorCallbackCall.this, response);}}});}public void onFailure(Call<T> call, final Throwable t) {callbackExecutor.execute(new Runnable() {public void run() {callback.onFailure(ExecutorCallbackCall.this, t);}});}});}public boolean isExecuted() {return delegate.isExecuted();}public Response<T> execute() throws IOException {return delegate.execute();}public void cancel() {delegate.cancel();}public boolean isCanceled() {return delegate.isCanceled();}"CloneDoesntCallSuperClone") // Performing deep clone.(public Call<T> clone() {return new ExecutorCallbackCall<>(callbackExecutor, delegate.clone());}public Request request() {return delegate.request();}}类里面有两个关键方法:enqueue(用于异步执行网络请求)、request(用于同步执行网络请求)。
- enqueue方法,是callbackExecutor.execute(Runnable),这又得联想到刚才构建Android platform时创建了一个defaultCallbackExecutor,将runnable post到主线程。
- 再结合上面写的例子,相信你已经大致了解执行过程了。
将返回结果转成我们需要的类型
- 最后补上一个点,怎么转换类型,例子中我们用的是Gson,所以我就结合着代码说一下它是怎么转换的。首先我们在构造Retrofit时传入了一个 GsonConverterFactory.create()。
|
|
- 在GsonConvertFactory中有两个非常重要的方法:
|
|
- 上面提到的网络请求,最终会由okhttp执行,最后拿到回调结果后,会执行到ServiceMethod中:
|
|
- 我们来看看GsonRequestBodyConverter的convert方法都做了什么
|
|
- 最后回调给Callback的onSuccess或者onFailure。
- 中间略去一些过程,我觉得结合代码是比较容易理解的,我这里就列出一个大致的流程思路。
总结
- Retrofit的设计非常巧妙,将各个模块都解耦,可以根据自己的需要来组装。因此不得不对大牛的设计感到惊叹。
- 第一次看可能会看的有点迷糊,建议结合源码多次看。相信每次的收获都会不同吧。