美文网首页Android心得总结
Retrofit 2.4.0 工作流程源码解析

Retrofit 2.4.0 工作流程源码解析

作者: BzCoder | 来源:发表于2019-07-27 20:54 被阅读2次

    本文参考 Retrofit分析-漂亮的解耦套路
    图片来源 Retrofit分析-漂亮的解耦套路
    源码版本:Retrofit2.4.0 Rxjava2 2.2.0

    Refrofit流程图

    Retrofit原理

    我们根据这张流程图来对着源码慢慢来看。一切从左上角开始。

    1.retrofit.create(service.class)

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

    这里主要用到了JDK的动态代理功能。实现InvocationHandler接口即可。通过loadServiceMethod()代理生成传入Service的代理类ServiceMethod。下方的OkHttpCall是OKhttp3的封装类。最后通过serviceMethod.adapt(okHttpCall)将okHttpCall设置回serviceMethod中,以便之后在各种CallAdapter中使用。callAdapter是一个适配器,适配成其他平台可以使用的类型,比如转化为Rxjava或者Rxjava2。

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

    这里回头再看下loadServiceMethod()方法,他设置了缓存池,自身是通过ServiceMethod.Builder()建造者来生成,此方法将收集传入的service方法包含的注解信息以及在Retrofit.Builder()方法中配置的BaseUrl,okHttpClient,Converter,CallAdapter并将其转化为参数设置到result中。此时我们传入的service中所有数据都已经装配完毕了。此时上图中我们已经进行到了图中CallAdapter.adapt。由上述代码我们可知retrofit.create({service}).{service.method}.实际调用的是callAdapter.adapt(call)。

    2.CallAdapter.adapt(call)

    CallAdapter实现类

    完成了以上配置工作,接下来就要开始动手干活了。CallAdapter有四个实现类,以现在的最常用的Rxjava2.2.0 + Retrofit2.4.0模式为例,所以最终调用的是RxJava2CallAdapter中的adapt方法。(当然RxJava2CallAdapter在顶部图片是已经没有了)

     @Override public Object adapt(Call<R> call) {
        Observable<Response<R>> responseObservable = isAsync
            ? new CallEnqueueObservable<>(call)
            : new CallExecuteObservable<>(call);
       ...
      }
    

    上述代码中CallEnqueueObservable与CallExecuteObservable对应Okhttp中的异步请求和同步请求。这里通过RxJava2CallAdapterFactory.create()/createAsync()去设置,本质是改变Okhttp请求方法来控制同步异步,但是现在很多做法是通过Rxjava2去调度使用的时候去调度线程,所以可以看到很多库封装Retrofit是使用RxJava2CallAdapterFactory.create()的。但是我们这里还是着重看下异步请求。

    3.CallEnqueueObservable

    final class CallEnqueueObservable<T> extends Observable<Response<T>> {
    ....
      @Override protected void subscribeActual(Observer<? super Response<T>> observer) {
        // Since Call is a one-shot type, clone it for each new observer.
        Call<T> call = originalCall.clone();
        CallCallback<T> callback = new CallCallback<>(call, observer);
        observer.onSubscribe(callback);
        call.enqueue(callback);
      }
    private static final class CallCallback<T> implements Disposable, Callback<T> {
    ....
        CallCallback(Call<?> call, Observer<? super Response<T>> observer) {
          this.call = call;
          this.observer = observer;
        }
    
        @Override public void onResponse(Call<T> call, Response<T> response) {
          if (call.isCanceled()) return;
          try {
            observer.onNext(response);
            if (!call.isCanceled()) {
              terminated = true;
              observer.onComplete();
            }
          } catch (Throwable t) {
          ....
              }
            }
          }
        }
    
        @Override public void onFailure(Call<T> call, Throwable t) {
       ....
        }
    ...
    }
    

    CallEnqueueObservable重写了subscribeActual,subscribeActual会在subscribe中调用。其中CallCallback是连接Retrofit,Rxjava2,OKhttp的桥梁,Okhttp产生回调后会传回Retrofit,最终通知Rxjava2。这里也走到了最终网络请求的方法call.enqueue(callback),点进去我们就可以看到熟悉的OKHttp的网络方法。

    4.call.enqueue(new okhttp3.Callback()

     call.enqueue(new okhttp3.Callback() {
          @Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {
            Response<T> response;
            try {
              response = parseResponse(rawResponse);
            } catch (Throwable e) {
              callFailure(e);
              return;
            }
    
            try {
              callback.onResponse(OkHttpCall.this, response);
            } catch (Throwable t) {
              t.printStackTrace();
            }
          }
    
          @Override public void onFailure(okhttp3.Call call, IOException e) {
            callFailure(e);
          }
    
          private void callFailure(Throwable e) {
            try {
              callback.onFailure(OkHttpCall.this, e);
            } catch (Throwable t) {
              t.printStackTrace();
            }
          }
        });
      }
    

    在call.enqueue中还看到中callback.onResponse(OkHttpCall.this, response)callback.onFailure(OkHttpCall.this, e)此处的callback就是observer.onSubscribe(callback)中设置的callback,就此回到Retrofit的回调。在CallCallback.onResponse中又有observer.onNext(response)最后回到了Rxjava2。至此流程结束。接下来就全部是Rxjava2的事儿了。

    5.总结

    Retrofit2在灵活解耦方面做的十分精妙,需要多看几次学习学习其中的思想。如果文章中描述有误,欢迎在留言中指出。

    相关文章

      网友评论

        本文标题:Retrofit 2.4.0 工作流程源码解析

        本文链接:https://www.haomeiwen.com/subject/gjterctx.html