Retrofit2.0源码解析(简版)
来源:互联网 发布:mac官网口红价格 编辑:程序博客网 时间:2024/05/01 18:06
出处:http://www.jianshu.com/p/69a3aff6bfac
Retrofit 是square公司开发的一款对OKHttp进行了进一步封装的网络框架,现在也是android网络请求中非常火的一个网络请求框架,最近在准备面试的时候也刚好复习到了这一块,然后花了几天时间简单地看了下Retrofit2.0源码,分享一下。若有不对的地方,欢迎指正。
Retrofit2.0原理
Retrofit2.0用了动态代理技术,通过解析注解生成Http请求,把请求交给OkHttp,然后通过我们设置的ConverterFactory进行serialization和deserialization,最后通过CallAdapter把结果进行进一步适配,实现了对Rxjava,Guava和java8的支持。
Retrofit2.0所使用的动态代理
在官方给的samples中,我们首先得创建一个retrofit对象,然后通过该对象创建一个我们要代理的实例,即:
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);
这个Github就是我们网络请求的接口:
public interface GitHub { @GET("/repos/{owner}/{repo}/contributors") Call<List<Contributor>> contributors( @Path("owner") String owner, @Path("repo") String repo); }
在这里,retrofit使用了builder模式,我们可以在此设置请求的URL,ConverterFactory(此处用了Gson解析,当然你也可以自定义数据解析器,只要你的解析器继承 Converter.Factory就行),或者设置回调时的适配器。在retrofit中提供了三种CallAdapterFactory
:GuavaCallAdapterFactory
,Java8CallAdapterFactory
和RxJavaCallAdapterFactory
。比如要把response封装成rxjava的Observeble,然后对其进行流式操作:
Retrofit.Builder.addCallAdapterFactory(newRxJavaCallAdapterFactory().create());
然后我们点进去retrofit.create(GitHub.class)会发现:
@SuppressWarnings("unchecked") // Single-interface proxy creation guarded by parameter safety. 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 (method.getDeclaringClass() == Object.class) { return method.invoke(this, args); } //对java8兼容 if (platform.isDefaultMethod(method)) { return platform.invokeDefaultMethod(method, service, proxy, args); } //看缓存里面有没有这个method,要是有,就返回,要是没有,就生成一个,然后加入缓存 ServiceMethod serviceMethod = loadServiceMethod(method); //生成一个OkHttpCall对象 OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args); //调用OkHttp,然后根据okHttpCall返回rejava的Observe对象或者返回Call return serviceMethod.callAdapter.adapt(okHttpCall); } }); }
这里的Platform
其实是检测retrofit所运行的平台,是java8还是android还是ios。这里主要是在builder的时候,如果没有设置适配器,那么retrofit就会通过运行时的不同平台,然后选择不同的CallAdapterFactory
。从上面的代码可以看出,create
方法返回了一个动态代理对象,通过Github
接口生成代理类,并将代理类的实现交给 InvocationHandler
作为具体的实现。这里使用动态代理的好处是简化复杂的网络请求和解析、封装ServiceMethod。
主要的网络请求类
OkHttpCall
:这个类主要实现了Call<T>
接口,主要的作用就是发送一个HTTP请求,retrofit默认的也是这个类,我们也可以根据不同的情况实现自己的Call类,这种设计很插件化。在OkHttpCall内部提供了异步和同步两种方法来发送请求,分别是同步的OkHttpCall.execute()
和异步的OkHttpCall.enqueue()
,在异步操作中:
@Override public void enqueue(final Callback<T> callback) { if (callback == null) throw new NullPointerException("callback == null"); okhttp3.Call call; Throwable failure; synchronized (this) { if (executed) throw new IllegalStateException("Already executed."); executed = true; call = rawCall; failure = creationFailure; if (call == null && failure == null) { try { call = rawCall = createRawCall(); } catch (Throwable t) { failure = creationFailure = t; } } } if (failure != null) { callback.onFailure(this, failure); return; } if (canceled) { call.cancel(); } call.enqueue(new okhttp3.Callback() { @Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) throws IOException { Response<T> response; try { response = parseResponse(rawResponse); } catch (Throwable e) { callFailure(e); return; } callSuccess(response); } @Override public void onFailure(okhttp3.Call call, IOException e) { try { callback.onFailure(OkHttpCall.this, e); } catch (Throwable t) { t.printStackTrace(); } } private void callFailure(Throwable e) { try { callback.onFailure(OkHttpCall.this, e); } catch (Throwable t) { t.printStackTrace(); } } private void callSuccess(Response<T> response) { try { callback.onResponse(OkHttpCall.this, response); } catch (Throwable t) { t.printStackTrace(); } } }); }
这里的call就是okhttp3.Call
,在这里通过用call.enqueue(...)
把请求交给okhttp的队列中,然后再通过异步回调切换到主线程,这里线程切换主要是通过前面的retrofit在build()的时候,Platform
检测到运行环境在android的时候,就会跳到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); } } }
看到上面的MainThreadExecutor
就能看出来,在execute()的时候,retrofit获取了主线程的handler,然后在UI线程执行网络请求回调后的数据显示等操作。
网络请求流程总结
- 首先,在
Retrofit
build的时候,我们假设设置了newRxJavaCallAdapterFactory().create()
,还加上了addConverterFactory(GsonConverterFactory.create())
。 - 在当我们调用
github.contributors("square", "retrofit");
的时候,其实是调用了动态代理的InvocationHandler
,在InvocationHandler
中,我们看到有一个ServiceMethod
,这里用了缓存,缓存了之前调用过的网络请求的方法,loadServiceMethod(method)
方法检测缓存里面有没有调用过这个method,要是有,就返回,要是没有,就生成一个(此时会解析contributors()
,解析我们在contributors()
上面加的Annotation等,以便后面封装成request),然后加入缓存。 - 然后生成一个
OkHttpCall
,serviceMethod.callAdapter.adapt(OkHttpCall)
,此时的callAdapter
就是RxJavaCallAdapterFactory
。 - 在
InvocationHandler
中的最后一行代码中,return serviceMethod.callAdapter.adapt(okHttpCall);
此时调用了RxJavaCallAdapterFactory.adapt()
方法,返回我们想要的对象,比如android里面默认的Call<>,或者我们这里设置了RxJavaCallAdapterFactory,所以返回的是Observable<>。 - 当我们调用了rxjava的subscribe方法的时候(或者调用Call的enqueue方法) ,做了下面几件事:
- 首先执行
okHttpCall
的execute()方法把网络请求交给okHttp,当完成请求后,会对网络请求的结果进行解析,在解析时,会调用serviceMethod.toResponse(catchingBody)
,这里会通过我们之前设置的GsonConverterFactory
来解析返回的数据(比如通过GSON解析什么的),然后再生成一个Response
类. - 再回调到
ExecutorCallAdapterFactory
(这个CallAdapterFactory
是之前在retrofit的build()方法中通过Platform
检测环境,然后设置的一个CallAdapterFactory
),这个CallAdapterFactory
的adapt()中生成了一个ExecutorCallbackCall
对象,在这个ExecutorCallbackCall
的enqueue(CallBack)
中,会调用MainThreadExecutor
的execute()
方法,此时就是之前说的利用handler切换到主线程。 - 最后因为我们使用了rxjava,所以在这里会对返回的call对象进行了进一步封装,生成了我们需要的
Observable<Response>
,最后我们就可以在主线程中进行开心的rx的流式操作了!
- 首先执行
- Retrofit2.0源码解析(简版)
- Retrofit2.0源码解析
- Retrofit2.0源码解析
- Retrofit2.0源码解析
- Retrofit2.0源码解析
- Retrofit2.0源码解析
- Retrofit2.0源码简要解析
- Retrofit2源码解析(一)
- Retrofit2源码解析(一)
- Retrofit2源码解析
- Retrofit2 源码解析
- Retrofit2 源码解析
- Retrofit2 源码解析
- Retrofit2 源码解析
- Retrofit2 源码解析
- Retrofit2 源码解析
- Retrofit2 源码解析
- Retrofit2.1源码解析
- 开发中遇到的问题--java.lang.IllegalStateException
- Spring MVC文件上传下载实践
- Storm Tick
- 织梦去除无效内容以及添加有效内容
- 支持上下拉刷新的RecycleView,基于androidPullToRefresh,添加RecycleView HeaderView
- Retrofit2.0源码解析(简版)
- 下载Windows版本的Redis
- 二叉树的最大节点
- http://blog.csdn.net/shangguanyunlan
- 哈希表(散列)的实现方法
- Setup Your Own Shadowsocks Server On Debian, Ubuntu, CentOS
- 教你上传本地代码到github
- BZOJ 1280: Emmy卖猪pigs 网络最大流,神奇建图
- Java Lambda(4)