Retrofit,OkHttp,Okio Square 安卓平台网络层三板斧源码学习
基于 retrofit 2.4.0-SNAPSHOT 版本 retrofit github 地址 :
https://github.com/square/retrofit
Retrofit 是 Square 安卓平台网络层三板斧最后一个项目,Retrofit 依赖 OkHttp 。Retrofit 让 http 网络请求更加清晰。
使用方式
一、声明一个接口,并用接口描述 request
public interface GitHubService { @GET("users/{user}/repos") Call<List<Repo>> listRepos(@Path("user") String user); }
二、方法上面的注释表示 request 的接口名 ,方法的返回类型就是 http 请求的返回值,方法的参数就是 http 的请求参数。
创建一个 Retrofit 客户端
Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://api.github.com/") .build(); GitHubService service = retrofit.create(GitHubService.class);
Retrofit 创建的时候指定了 request 的接口地址,然后调用 retrofit.create 方法创建一个 GitHubService 实例。
三、发起网络请求
Call<List<Repo>> repos = service.listRepos("octocat"); repos.execute().body()
上面的例子可以看到,retrofit.create() 方法会创建一个 GitHubService 实例,但是 GitHubService 本身是一个接口。为了了解 retrofit.create() 方法,我们先看下 Retrofit 的创建过程。
Retrofit 创建 Service 实例
创建 Retrofit 对象。
Retrofit 和 OkHttp 一样都是使用构建者模式创建对象。先看下 Retrofit.Builder 的 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(); } 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); }
创建 Retrofit 的时候需要传递一下几个参数
callFactory 用来创建一个实现了 okhttp3.Call.Factory 的对象,如果没有设置,默认为 OkHttpClient。
baseUrl 网络接口的地址。 -converterFactories 用来把服务器返回的数据转换为对象。
adapterFactories 用来发起网络请求。
callbackExecutor 是一个调度器,用来接收返回的数据,在 Android 上默认是封装了 handler 的 MainThreadExecutor
validateEagerly 是一个开关,如果为 true 会缓存创建的 ServiceMethod 。
我们再来看一下retrofit.create()源码
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, @Nullable 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); } }); }
这里用到了一个公共技术点之 Java 动态代理,create 方法传入一个 Class ,这个 Class 对象就是上文的 GitHubService 的 Class 。
GitHubService 的方法是由 InvocationHandler 代理实现的,重点看三行代码
...... ServiceMethod<Object, Object> serviceMethod =(ServiceMethod<Object, Object>) loadServiceMethod(method); OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args); return serviceMethod.callAdapter.adapt(okHttpCall);
第一行 loadServiceMethod(method)
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; }
这里创建了一个 ServiceMethod 对象。
第二行 new OkHttpCall<>(serviceMethod, args)
OkHttpCall(ServiceMethod<T, ?> serviceMethod, @Nullable Object[] args) { this.serviceMethod = serviceMethod; this.args = args; }
创建了一个 OkHttpCall ,serviceMethod 和 args 是 OkHttpCall 的成员函数。
所以,
第三行 serviceMethod.callAdapter.adapt(okHttpCall)
这里需要明白 serviceMethod.callAdapter 是怎么来的
1. 在 ServiceMethod.Builder.build() 中调用 createCallAdapter() 2. 在 createCallAdapter() 中会找到 (CallAdapter<T, R>) retrofit.callAdapter(returnType, annotations) 3. 在 callAdapter() 中调用 nextCallAdapter 4. nextCallAdapter 会遍历 adapterFactories 返回一个 CallAdapter。
这里再回头看下 adapterFactories Retrofit.Builder.build() 方法中
List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories); adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
而在 Retrofit.nextCallAdapter() 中
int start = adapterFactories.indexOf(skipPast) + 1; for (int i = start, count = adapterFactories.size(); i < count; i++) { CallAdapter<?, ?> adapter = adapterFactories.get(i).get(returnType, annotations, this); if (adapter != null) { return adapter; } }
如果没有设置 AdapterFactory 将会使用一个默认的 AdapterFactory
CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) { if (callbackExecutor != null) { return new ExecutorCallAdapterFactory(callbackExecutor); } return DefaultCallAdapterFactory.INSTANCE; }
所以如果我们设置了一个 RxJavaCallAdapterFactory,就会返回 RxJavaCallAdapterFactory。
整个创建Retrofit的过程流程为:
发起网络请求
通过 retrofit.create() 我们可以知道,retrofit.create() 返回的是一个代理对象InvocationHandler ,那么在执行
Call<List> repos = service.listRepos("octocat"); 方法时,调用的实际上是 callAdapter.adapt(okHttpCall),以 DefaultCallAdapterFactory 为例
@Override public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) { if (getRawType(returnType) != Call.class) { return null; } final Type responseType = Utils.getCallResponseType(returnType); return new CallAdapter<Object, Call<?>>() { @Override public Type responseType() { return responseType; } @Override public Call<Object> adapt(Call<Object> call) { return call; } }; }
结合 retrofit.create() 方法可以得知这里返回的是一个 OkHttpCall 对象。
接下来使用 OkHttpCall.execute() 或者异步执行 enqueue(Callback callback)
这两种方式都会调用 createRawCall() 创建一个 okhttp3.Call
private okhttp3.Call createRawCall() throws IOException { Request request = serviceMethod.toRequest(args); okhttp3.Call call = serviceMethod.callFactory.newCall(request); if (call == null) { throw new NullPointerException("Call.Factory returned null."); } return call; }
此处的 serviceMethod.callFactory 就是 retrofit.create() 中创建的 OkHttpClient() 后面的内容都是由 Okhttp 模块接管,进行网络请求,参考okHttp 框架源码学习
然后调用 parseResponse(call.execute())
Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException { ResponseBody rawBody = rawResponse.body(); …… 省略一些 http 返回值处理逻辑 …… try { T body = serviceMethod.toResponse(catchingBody); return Response.success(body, rawResponse); } …… }
okHttp 请求网络的返回数据,会交给 serviceMethod.toResponse
R toResponse(ResponseBody body) throws IOException { return responseConverter.convert(body); }
在 ServiceMethod.Builder.build() 方法中可以找到 responseConverter 是通过 createResponseConverter() 方法的返回对象。
createResponseConverter() 只是报包裹了 retrofit.responseBodyConverter(responseType, annotations) 方法。
retrofit.responseBodyConverter() 继续跟踪下去会得知,返回的是 converterFactories 数组的第 0 个对象,也就是内置的 BuiltInConverters.responseBodyConverter() 方法返回的 BufferingResponseBodyConverter
static final class BufferingResponseBodyConverter implements Converter<ResponseBody, ResponseBody> { static final BufferingResponseBodyConverter INSTANCE = new BufferingResponseBodyConverter(); @Override public ResponseBody convert(ResponseBody value) throws IOException { try { // Buffer the entire body to avoid future I/O. return Utils.buffer(value); } finally { value.close(); } } }
再看一下 Utils.buffer(value)
static ResponseBody buffer(final ResponseBody body) throws IOException { Buffer buffer = new Buffer(); body.source().readAll(buffer); return ResponseBody.create(body.contentType(), body.contentLength(), buffer); }
最终会返回一个重新封装的 Okhttp 框架的 ResponseBody 对象,过程如下:
最后来个总结
第一步创建一个Retrofit对象
通过 Retrofit.onCreate()方法把我们所定义的接口转化为接口实例并使用接口中的方法
最终的实例都会调用okHttp的call,retrofit用于OKhttp的,比较灵活
相信自己,没有做不到的,只有想不到的
作者:codeGoogle