OkHttp
偷贴一张Piasy的图
基本用法
1 | OkHttpClient client=new OkHttpClient.Builder().build(); |
同步请求
先从同步请求入手,newCall
返回的是RealCall实例,RealCall的execute
1 | protected void execute() { |
主要还是调用了getResponseWithInterceptorChain
,最后在通知dispatcher结束。其他的都是取消、错误异常处理
1 | Response getResponseWithInterceptorChain() throws IOException { |
为请求添加拦截器(下面会讲),先添加自定义的拦截器,然后添加一堆默认的桥接、缓存等拦截器,最后添加的是CallServerInterceptor,划重点,要考的
最后调用RealInterceptorChain实例的proceed
1 | public Response proceed(Request request, StreamAllocation streamAllocation, HttpCodec httpCodec, |
第一次传进来的index为0,后面每次都是index+1,就是依次按上面interceptors的添加顺序,把拦截器取出来,调用intercept的方法。在拦截器内部又调用proceed,一直到最后来调用到上面说的最后添加的CallServerInterceptor这个拦截器来进行真正的网络操作。
1 |
|
实际上使用的是HttpCodec类来进行socket操作,基于Okio封装了BufferSink和BufferSource。
拦截器
1 | public interface Interceptor { |
Intercept只有一个内部类Chain,一个intercept
方法,参数为Chain的实例。
通过这个chain.request
和chain.proceed
来分别对Request和Response做额外的处理。
下面是一个自定义的拦截器,输出请求/响应的日志
1 | class LoggingInterceptor implements Interceptor { |
异步请求
下面再来看看异步请求,重新贴一下代码
1 | client.newCall(request).enqueue(new Callback() { |
RealCall的enqueue
1 | public void enqueue(Callback responseCallback) { |
主要是使用AsyncCall包装一下回调请求,然后通过client.dispatcher()的enquue
来执行
1 | synchronized void enqueue(AsyncCall call) { |
如果没有超过最大请求数,就使用executorService()返回的线程池实例执行call,否则添加到等待的readyAsyncCalls中。
再来介绍一下AsyncCall,是RealCall的一个内部类,继承自NamedRunnable,NamedRunnable实现Runnable。NamedRunnable在重写run
方法的时执行了一个抽象方法execute
,由AsyncCall来实现。所以当线程执行异步请求的时候实际上走的就是AsyncCall的execute
方法。
1 | protected void execute() { |
跟RealCall的execute很像啊,getResponseWithInterceptorChain
来执行。基本可以说明异步的请求跟同步的区别就是加了个线程池来实现网络请求,并通过callback回调。
Retrofit
再来分析一下Retrofit是如何对OkHttp进行封装的
基本用法
这块暂时不看,看下一个
1 | public static RetrofitClient getInstance() { |
↓↓看这个↓↓
1 | public interface BlogService { |
create
1 | public <T> T create(final Class<T> service) { |
通过动态代理技术直接返回代理类实例
动态代理
通过jdk在内存中动态生成一个代理对象,涉及Proxy类的静态方法newProxyInstance
和InvocationHandler
接口。
下面大体讲一下使用,直接手打可能有点错误,意思到了就行了。。。
1 | //接口 |
再回到create中InvocationHandler的invoke方法的代码
1 |
|
loadServiceMethod
1 | ServiceMethod<?, ?> loadServiceMethod(Method method) { |
先从缓存中查找,如果没有就通过new ServiceMethod.Builder<>(this, method).build()
新建一个
1 | public ServiceMethod build() { |
主要逻辑如上
createCallAdapter
是根据委托类方法的返回值,来确定要使用的CallAdapter,比如我们的返回值是Observable
,那么就会使用RxJava2CallAdapterFactory
,如果我们在创建Retrofit实例的时候没有通过addCallAdapterFactory(RxJava2CallAdapterFactory.create())
来添加与返回值相应的处理函数,那么这里就会抛出异常。createResponseConverter
也是同样的道理,比如我们使用addConverterFactory
添加GsonConverterFactory
parseMethodAnnotation
解析每个方法的注解GET、POST、PUT等等
new OkHttpCall()
1 | final class OkHttpCall<T> implements Call<T> { |
对内部okhttp3.Call类型的rawCall
进行封装,默认使用的是OkHttpClient的实例。
1 | serviceMethod.callFactory = = builder.retrofit.callFactory(); //serviceMethod.java |
parseResponse
OkHttpCall内部对返回值做了处理,通过responseConverter
1 | T body = serviceMethod.toResponse(catchingBody); |
callAdapter.adapt
再关注动态代理方法invoke
的返回值
1 | return serviceMethod.callAdapter.adapt(okHttpCall); |
调用serviceMethod的成员变量callAdapter.adapt来适配委托类的方法返回值。
在loadServiceMethod中创建ServiceMethod时,callAdapter = createCallAdapter()
,跟进
1 | private CallAdapter<T, R> createCallAdapter() { |
1 | public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) { |
通过adapterFactories.get(i).get(returnType, annotations, this);
可以知道是遍历retrofit的adapterFactories,并调用每个item的get
方法来获取与返回值对应的Adapter
adapterFactories
这个adapterFactories是在构造Retrofit时由Builder默认添加了一个
1 | public Retrofit build() { |
以默认的DefaultCallAdapterFactory
为例,看看他的get方法
1 | final class DefaultCallAdapterFactory extends CallAdapter.Factory { |
返回的new CallAdapter
对传入的OkHttpCall毫无包装,直接返回Call,毕竟是默认的。
我们再以常用的RxJava2CallAdapterFactory
为例,看RxJava2CallAdapterFactory的get方法。
1 |
|
返回的是RxJava2CallAdapter的实例,在看看RxJava2CallAdapter的adapt方法。
1 | public Object adapt(Call<R> call) { |
根据各种条件做了一些判断,对Call进行封装,具体见源码。
call.enqueue
1 | public void enqueue(final Callback<T> callback) { |
再上一张图来帮助理解create的这个三部曲。