Retrofit 分析

先上一个RetrofitHelper 使用kotlin的默认单例模式

object RetrofitHelper {
    private var mOkHttpClient: OkHttpClient? = null
    fun getGankApiService() = createApi(GankApi::class.java, "http://gank.io/")
    private fun <T> createApi(clazz: Class<T>, baseUrl: String): T {
        if (mOkHttpClient == null)
            initOkHttpClient()
        val retrofit = Retrofit.Builder()
            .baseUrl(baseUrl)
            .client(mOkHttpClient!!)
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
            .addConverterFactory(GsonConverterFactory.create())
            .build()
        return retrofit.create(clazz)
    }

    private fun initOkHttpClient() {
        val httpLoggingInterceptor = HttpLoggingInterceptor()
        httpLoggingInterceptor.level = HttpLoggingInterceptor.Level.BODY
        if (mOkHttpClient == null) {
            synchronized(RetrofitHelper::class.java) {
                if (mOkHttpClient == null) {
                    //val cache = Cache(File(.getCacheDir(), "HttpCache"), 1024 * 1024 * 1)
                    mOkHttpClient = OkHttpClient.Builder()
                        //.cache(cache)
                        .addInterceptor(httpLoggingInterceptor)
                        .retryOnConnectionFailure(true)
                        .connectTimeout(30, TimeUnit.SECONDS)
                        .writeTimeout(20, TimeUnit.SECONDS)
                        .readTimeout(20, TimeUnit.SECONDS)
                        .build()
                }
            }
        }
    }
}

Retrofit.java中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.adapt(okHttpCall);
          }
        });
  }

create 先先检查service,不是接口报错,接口有继承也报错
返回 动态代理代理接口,加入回掉
1.确定平台,安卓平台
2.如果是object类的方法直接调用
3.平台默认方法(不支持,一直返回false)
4.新建ServiceMethod,把一个接口转换到一个httpcall

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;
  }

5.ServiceMethod的build方法 新建callAdapter,到retrofit的callAdapterFactories抽象工厂缓存里用get生产实例
6.callAdapter的返回类型才是最终的返回类型
7.生成responseConverter,类似上面也是抽象工厂从retrofit缓存生产转换器
8.后续 把方法注解路径等都抽出来转换到内置属性
9.OkHttpCall用ServiceMethod来构造,由okhttpclient生产
10.OkHttpCall是okhttp3.Call的泛型版本,okhttp3.Call嵌套调用OkHttpCall的onresponse和onFailure;返回还会被parseResponse做成功转换
11.默认calladapter情况下serviceMethod.adapt(okHttpCall) 返回okHttpCall

addCallAdapterFactory(RxJava2CallAdapterFactory.create())

callAdapterFactories抽象工厂模式 get生产实例
nextCallAdapter里获得callAdapterFactories中第一个的CallAdapter,先自定义后默认
RxJava2CallAdapter的adapt新建Observable

OKHTTP3

newcall新建realcall代表一次请求,
enqueue异步任务的时候交给clinet的Dispatcher的enqueue
enqueue的是一个runnable (子类实现AsyncCall)交给线程池
异步任务使用Dispatcher处理,内部主要是一个线程池,不保留存活60秒无限数量

public synchronized ExecutorService executorService() {
    if (executorService == null) {
      executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
          new SynchronousQueue<Runnable>(), Util.threadFactory("OkHttp Dispatcher", false));
    }
    return executorService;
  }

AsyncCall的run调用execute 是异步发生的callback

@Override protected void execute() {
      boolean signalledCallback = false;
      try {
        Response response = getResponseWithInterceptorChain();
        if (retryAndFollowUpInterceptor.isCanceled()) {
          signalledCallback = true;
          responseCallback.onFailure(RealCall.this, new IOException("Canceled"));
        } else {
          signalledCallback = true;
          responseCallback.onResponse(RealCall.this, response);
        }
      } catch (IOException e) {
        if (signalledCallback) {
          // Do not signal the callback twice!
          Platform.get().log(INFO, "Callback failure for " + toLoggableString(), e);
        } else {
          eventListener.callFailed(RealCall.this, e);
          responseCallback.onFailure(RealCall.this, e);
        }
      } finally {
        client.dispatcher().finished(this);
      }
    }

response使用了责任链设计模式

1.内部添加了多个拦截器的ArrayList
2.使用index作为索引,调用第一个chain的proceed
3.RealInterceptorChain作为实现,proceed的时候先检查index是否越界(执行结束)
4.新建下一个RealInterceptorChain并传入index+1的位置
5.使用当前的Interceptor 处理下一个RealInterceptorChain;其实就是执行当前的Interceptor的intercept方法,主要内容:用当前Interceptor修改下一个RealInterceptorChain,然后调用下一个RealInterceptorChain的proceed方法,循环处理。(ConnectInterceptor 添加了HttpCodec 传给了下游的CallServerInterceptor)
6.CallServerInterceptor是最后一个拦截器负责请求数据,只会被倒数第二个调用,不再调用下一个了
7.HttpCodec有http1和2的各自实现,CallServerInterceptor联网的过程是用HttpCodec的高层次接口实现的
8.interface HttpCodec接口的实现,最终交给Okio来处理(Sink)
9.对网络的处理,最终是socket的java.io.OutputStream java实现

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 一、前言 在《OkHttp深入分析——基础认知部分》对 OkHttp 源码的工程已经有一个大致的了解了,这篇文章里...
    仰简阅读 4,681评论 0 4
  • OkHttp源码的samples的简单使用的示例: public static void main(String....
    _warren阅读 4,256评论 0 1
  • 关于okhttp是一款优秀的网络请求框架,关于它的源码分析文章有很多,这里分享我在学习过程中读到的感觉比较好的文章...
    蕉下孤客阅读 9,018评论 2 38
  • 这篇文章主要讲 Android 网络请求时所使用到的各个请求库的关系,以及 OkHttp3 的介绍。(如理解有误,...
    小庄bb阅读 5,020评论 0 4
  • 周末两天,都睡到死,丝毫不夸张,我都不知道自己是怎么醒过来的,因为,根本醒不了,被太阳晒的眼睛睁开,但爬不起来,翻...
    你说我听好么阅读 2,490评论 0 0

友情链接更多精彩内容