Retrofit源码解析
来源:互联网 发布:外置光驱盒 mac 编辑:程序博客网 时间:2024/04/30 09:08
Retrofit源码结构
Retrofit: 通过注解,把一个Java接口转化成一个http 请求,底层网络请求基于okhttp
从Retrofit源码结构可以看出,Retrofit 源码分成两部分
一部分是包retrofit2.http里面的,在Java接口方法中使用,用来控制http行为的注解。
一部分是retrofit2里面的,负责把REST API转化成Java接口。
Retrofit和okhttp的关系
retrofit依赖okhttp库,retrofit 所有的网络请求都是由okhttp处理,可以说retrofit是对okhttp封装了,让其使用更加简单方便。
okhttp 准确来说是一个Java库,没有Android中主线程和工作线程的概念,Android有两个限制,第一不能再主线程中直接请求网络,第二不能在工作线程中直接更新UI,所以,如果我们在Android中直接使用okhttp,需要用到Handler来传递请求结果。而如果使用retrofit,则不需要我们去创建线程执行网络请求,也不需要使用Handler把请求结果从工作线程传递到主线程。retrofit直接在主线程中发起异步请求,最后收到请求结果也是在主线程中,非常方便。
主要类和方法
Retrofit:retrofit框架的入口类,主要有两个功能:
1、通过内部类Builder配置构建Retrofit实例。Builder主要配置选项:
1. client(OkHttpClient client) :设置一个配置好的OkHttpClient实例,不配置的话retrofit会默认new一个。2. baseUrl(String baseUrl) :设置API地址。3. addConverterFactory(Converter.Factory factory) :设置一个数据转化工厂,比如把Json和实体类之间的转化。4. addCallAdapterFactory(CallAdapter.Factory factory):设置一个适配器工厂,方便和其他库配合使用,如RxJava。
另外,如果我们没有设置执行任务的线程池的话,Retrofit会根据不同的平台,得到默认的线程池。
if (callbackExecutor == null) { callbackExecutor = platform.defaultCallbackExecutor();}
Android 中默认的线程池:
static class Android extends Platform { @Override public Executor defaultCallbackExecutor() { return new MainThreadExecutor(); } @Override CallAdapter.Factory defaultCallAdapterFactory(Executor callbackExecutor) { return new ExecutorCallAdapterFactory(callbackExecutor); } static class MainThreadExecutor implements Executor { private final Handler handler = new Handler(Looper.getMainLooper()); @Override public void execute(Runnable r) { handler.post(r); } }}
从上面代码可以看到,先会创建一个在主线程中的Handler,然后默认线程池执行的任务都是在Android的主线程中执行的,这也是在Retrofit异步回调中我们能直接在里面更新UI的原因。
另外,Retrofit根据不同使用平台,会默认添加一个CallAdapterFactory
List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
Android 中添加的是ExecutorCallAdapterFactory:
2、通过Retrofit的create方法,实现描述http请求的Java接口。
// 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");
我们在使用Retrofit时,首先要通过Retrofit实例来得到一个请求接口的实例(github),然后调用这个实例的一个方法(contributors)构造一个Call对象。这个过程主要是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, 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); OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args); return serviceMethod.callAdapter.adapt(okHttpCall); } });}
当调用接口里面方法的时候(github.contributors(“square”, “retrofit”) ),会执行InvocationHandler里面的内容,通过反射,得到调用的method相关信息,然后构造ServiceMethod和OkHttpCall的实例,在Android中通过ExecutorCallAdapterFactory 把 OkHttpCall 进行转换 ExecutorCallbackCall:
return new CallAdapter<Call<?>>() { @Override public Type responseType() { return responseType; } @Override public <R> Call<R> adapt(Call<R> call) { return new ExecutorCallbackCall<>(callbackExecutor, call); }};
最后我们得到的Call对象实际上是ExecutorCallbackCall实例。得到Call实例之后,就可以通过call.enqueue进行网络请求,我们看看ExecutorCallbackCall中的enqueue方法:
@Override public void enqueue(final Callback<T> callback) { if (callback == null) throw new NullPointerException("callback == null"); delegate.enqueue(new Callback<T>() { @Override public void onResponse(Call<T> call, final Response<T> response) { callbackExecutor.execute(new Runnable() { @Override 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); } } }); } @Override public void onFailure(Call<T> call, final Throwable t) { callbackExecutor.execute(new Runnable() { @Override public void run() { callback.onFailure(ExecutorCallbackCall.this, t); } }); } });}
在ExecutorCallbackCall中的enqueue里面,又调用delegate.enqueue方法,这个delegate,其实是OkHttpCall对象,也就是调用OkHttpCall中的enqueue方法。
首先构造一个okhttp中的Request对象:
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的toRequest方法得到的:
Request toRequest(Object... args) throws IOException { RequestBuilder requestBuilder = new RequestBuilder(httpMethod, baseUrl, relativeUrl, headers, contentType, hasBody, isFormEncoded, isMultipart); @SuppressWarnings("unchecked") // It is an error to invoke a method with the wrong arg types. ParameterHandler<Object>[] handlers = (ParameterHandler<Object>[]) parameterHandlers; int argumentCount = args != null ? args.length : 0; if (argumentCount != handlers.length) { throw new IllegalArgumentException("Argument count (" + argumentCount + ") doesn't match expected count (" + handlers.length + ")"); } for (int p = 0; p < argumentCount; p++) { handlers[p].apply(requestBuilder, args[p]); } return requestBuilder.build();}
其中构造RequestBuilder的参数都是ServiceMethod 从Java接口中的注解解析出来的。
ServiceMethod: 从这个类的方法结构可以看出,这个类主要作用是把方法的注解解析成变量保存起来。
- 【Retrofit】Retrofit源码解析
- Retrofit源码解析
- Retrofit源码解析
- Retrofit源码解析
- Retrofit源码解析
- Retrofit源码解析
- Retrofit源码解析
- Android Retrofit源码解析
- Retrofit 源码解析
- Retrofit源码解析
- Retrofit源码解析:RxJavaCallAdapterFactory
- Retrofit源码解析---初始化
- Retrofit 源码解析
- Retrofit源码解析
- Retrofit源码解析
- Retrofit源码解析(一)
- Retrofit源码解析(二)
- Retrofit源码解析(三)
- 开启memcache 扩展
- mysql -redis 主从复制
- .aspx文件和.aspx.cs文件的区别与联系
- 快速找到本视图的控制器
- hdu 5276 钟表 (暴力+数学 )
- Retrofit源码解析
- 框模型、背景、渐变
- NYOJ 448 寻找最大数
- win10下visual studio2015无法找到stdio.h的解决方法
- Intent四种数据传递方式
- RTMP 协议学习总结
- 文本格式化 、 表格 、 浮动
- 四行代码求最大公约数(欧几里得算法)
- 62. Unique Paths