美文网首页
Retrofit流程分析

Retrofit流程分析

作者: VerseWang | 来源:发表于2020-07-21 23:33 被阅读0次

    1.先上代码流程图

    Retrofit.jpg

    2 代码发生了什么事情

    val retrofit = Retrofit.Builder()
                    .baseUrl("https://dossen-sh-resource.oss-cn-shenzhen.aliyuncs.com/appbundle/android/3.14.0/")
                    .addCallAdapterFactory(RxJava3CallAdapterFactory.create())
                    .addConverterFactory(GsonConverterFactory.create())
                    .build()
    
                val service = retrofit.create(RetrofitService::class.java)
                service.http
                    .map { "haha, wo lai la" }
                    .subscribe(
                        { next: String ->
                            Log.d(
                                "wangyang",
                                "  subscribe     next = $next"
                            )
                        }
                    ) { error: Throwable ->
                        Log.d(
                            "wangyang",
                            "   error    error = $error"
                        )
                    }
    

    2.1 第1到第5行代码分别发生了

    public Builder addCallAdapterFactory(CallAdapter.Factory factory) {
      callAdapterFactories.add(Objects.requireNonNull(factory, "factory == null"));
      return this;
    }
    
    public Builder addConverterFactory(Converter.Factory factory) {
      converterFactories.add(Objects.requireNonNull(factory, "factory == null"));
      return this;
    }
    

    将RxJava3CallAdapterFactory放到了callAdapterFactories集合中
    将GsonConverterFactory放到了converterFactories集合中,这很重要,因为后面会用到

    通过一个建造者模式,设置了baseUrl,Rxjava,Gson的工厂类 build()时如下代码:

    public Retrofit build() {
      if (baseUrl == null) {
        throw new IllegalStateException("Base URL required.");
      }
    
      okhttp3.Call.Factory callFactory = this.callFactory;
      if (callFactory == null) {
        callFactory = new OkHttpClient();
      }
    
      Executor callbackExecutor = this.callbackExecutor;
      if (callbackExecutor == null) {
        callbackExecutor = platform.defaultCallbackExecutor();
      }
    
      // Make a defensive copy of the adapters and add the default Call adapter.
      List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
      callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));
    
      // Make a defensive copy of the converters.
      List<Converter.Factory> converterFactories =
          new ArrayList<>(
              1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize());
    
      // Add the built-in converter factory first. This prevents overriding its behavior but also
      // ensures correct behavior when using converters that consume all types.
      converterFactories.add(new BuiltInConverters());
      converterFactories.addAll(this.converterFactories);
      converterFactories.addAll(platform.defaultConverterFactories());
    
      return new Retrofit(
          callFactory,
          baseUrl,
          unmodifiableList(converterFactories),
          unmodifiableList(callAdapterFactories),
          callbackExecutor,
          validateEagerly);
    }
    

    由于没有设置OkHttpClient,会创建OkHttpClient对象,并把建造者模式中的参数放在Retrofit中的构造函数当中,callFactory对应的是OkHttpClient

    2.2第7行代码发生了什么事情

    public <T> T create(final Class<T> service) {
    validateServiceInterface(service);
    return (T)
        Proxy.newProxyInstance(
            service.getClassLoader(),
            new Class<?>[] {service},
            new InvocationHandler() {
              private final Platform platform = Platform.get();
              private final Object[] emptyArgs = new Object[0];
    
              @Override
              public @Nullable 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);
                }
                args = args != null ? args : emptyArgs;
                return platform.isDefaultMethod(method)
                    ? platform.invokeDefaultMethod(method, service, proxy, args)
                    : loadServiceMethod(method).invoke(args);
              }
            });
    }
    

    只是用到了Java中的动态代理模式

    2.3第8到第22行代码发生了什么事情

    第8行执行的是动态代理,看动态代理模式里面的代码,正常情况下会调用loadServiceMethod(method).invoke(args)方法

    ServiceMethod<?> loadServiceMethod(Method method) {
    ServiceMethod<?> result = serviceMethodCache.get(method);
    if (result != null) return result;
    
    synchronized (serviceMethodCache) {
      result = serviceMethodCache.get(method);
      if (result == null) {
        result = ServiceMethod.parseAnnotations(this, method);
        serviceMethodCache.put(method, result);
      }
    }
    return result;
    

    }

    会在serviceMethodCache中取ServiceMethod对象,第一次是没有的,第二次及以后会取出对应的Method对象,会去调用以下方法,并将解析的Method的ServiceMethod对象放到serviceMethodCache集合当中

    result = ServiceMethod.parseAnnotations(this, method);
    

    看看这行代码发生了什么事情

    static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
    RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);

    Type returnType = method.getGenericReturnType();
    if (Utils.hasUnresolvableType(returnType)) {
      throw methodError(
          method,
          "Method return type must not include a type variable or wildcard: %s",
          returnType);
    }
    if (returnType == void.class) {
      throw methodError(method, "Service methods cannot return void.");
    }
    
    return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
    }
    

    传入了Retrofit和Method,Retrofit中是刚开始通过建造者模式生成的对象,里面有OkHttpClient,baseurl等,并调用了这行代码

    static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
      Retrofit retrofit, Method method, RequestFactory requestFactory) {
    boolean isKotlinSuspendFunction = requestFactory.isKotlinSuspendFunction;
    boolean continuationWantsResponse = false;
    boolean continuationBodyNullable = false;
    
    Annotation[] annotations = method.getAnnotations();
    Type adapterType;
    if (isKotlinSuspendFunction) {
      Type[] parameterTypes = method.getGenericParameterTypes();
      Type responseType =
          Utils.getParameterLowerBound(
              0, (ParameterizedType) parameterTypes[parameterTypes.length - 1]);
      if (getRawType(responseType) == Response.class && responseType instanceof ParameterizedType) {
        // Unwrap the actual body type from Response<T>.
        responseType = Utils.getParameterUpperBound(0, (ParameterizedType) responseType);
        continuationWantsResponse = true;
      } else {
        // TODO figure out if type is nullable or not
        // Metadata metadata = method.getDeclaringClass().getAnnotation(Metadata.class)
        // Find the entry for method
        // Determine if return type is nullable or not
      }
    
      adapterType = new Utils.ParameterizedTypeImpl(null, Call.class, responseType);
      annotations = SkipCallbackExecutorImpl.ensurePresent(annotations);
    } else {
      adapterType = method.getGenericReturnType();
    }
    
    CallAdapter<ResponseT, ReturnT> callAdapter =
        createCallAdapter(retrofit, method, adapterType, annotations);
    Type responseType = callAdapter.responseType();
    if (responseType == okhttp3.Response.class) {
      throw methodError(
          method,
          "'"
              + getRawType(responseType).getName()
              + "' is not a valid response body type. Did you mean ResponseBody?");
    }
    if (responseType == Response.class) {
      throw methodError(method, "Response must include generic type (e.g., Response<String>)");
    }
    // TODO support Unit for Kotlin?
    if (requestFactory.httpMethod.equals("HEAD") && !Void.class.equals(responseType)) {
      throw methodError(method, "HEAD method must use Void as response type.");
    }
    
    Converter<ResponseBody, ResponseT> responseConverter =
        createResponseConverter(retrofit, method, responseType);
    
    okhttp3.Call.Factory callFactory = retrofit.callFactory;
    if (!isKotlinSuspendFunction) {
      return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
    } else if (continuationWantsResponse) {
      //noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
      return (HttpServiceMethod<ResponseT, ReturnT>)
          new SuspendForResponse<>(
              requestFactory,
              callFactory,
              responseConverter,
              (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter);
    } else {
      //noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
      return (HttpServiceMethod<ResponseT, ReturnT>)
          new SuspendForBody<>(
              requestFactory,
              callFactory,
              responseConverter,
              (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter,
              continuationBodyNullable);
    }
    }
    

    此时将callFactory封装到了CallAdapted

    看第31-32行代码

    private static <ResponseT, ReturnT> CallAdapter<ResponseT, ReturnT> createCallAdapter(
      Retrofit retrofit, Method method, Type returnType, Annotation[] annotations) {
    try {
      //noinspection unchecked
      return (CallAdapter<ResponseT, ReturnT>) retrofit.callAdapter(returnType, annotations);
    } catch (RuntimeException e) { // Wide exception range because factories are user code.
      throw methodError(method, e, "Unable to create call adapter for %s", returnType);
    }
    }
    
    public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {
    return nextCallAdapter(null, returnType, annotations);
    }
    
    public CallAdapter<?, ?> nextCallAdapter(
      @Nullable CallAdapter.Factory skipPast, Type returnType, Annotation[] annotations) {
    Objects.requireNonNull(returnType, "returnType == null");
    Objects.requireNonNull(annotations, "annotations == null");
    
    int start = callAdapterFactories.indexOf(skipPast) + 1;
    for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
      CallAdapter<?, ?> adapter = callAdapterFactories.get(i).get(returnType, annotations, this);
      if (adapter != null) {
        return adapter;
      }
    }
    
    StringBuilder builder =
        new StringBuilder("Could not locate call adapter for ").append(returnType).append(".\n");
    if (skipPast != null) {
      builder.append("  Skipped:");
      for (int i = 0; i < start; i++) {
        builder.append("\n   * ").append(callAdapterFactories.get(i).getClass().getName());
      }
      builder.append('\n');
    }
    builder.append("  Tried:");
    for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
      builder.append("\n   * ").append(callAdapterFactories.get(i).getClass().getName());
    }
    throw new IllegalArgumentException(builder.toString());
    }
    

    callAdapterFactories,似曾相识,没错,就是通过建造者模式生成Rertofit时,生成RxJava3CallAdapterFactory时用到的,这里会取出这个对象,并调用get()方法,最终会返回RxJava3CallAdapter对象,同理,GsonConverterFactory也会生产出GsonResponseBodyConverter对象

    由于代码中没有加入协程,所以isKotlinSuspendFunction为false,会生成CallAdapted对象,并将RxJava3CallAdapter放到构造函数当中,并赋值给CallAdapted的成员变量callAdapter,这也很重要

    return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
    

    就回到了动态代理当中的loadServiceMethod(method)方法,由此可见,loadServiceMethod是将CallAdapted对象放到了集合当中。

    当调用loadServiceMethod(method).invoke(args)中的invoke(args)方法时,会调用CallAdapted的父类HttpServiceMethod的invoke(args)方法

    final @Nullable ReturnT invoke(Object[] args) {
    Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
    return adapt(call, args);
    }
    

    生成了OkHttpCall对象,并又将callFactory封装到了OkHttpCall中,并调用adapt(call, args)实现方法在CallAdapted中

    protected ReturnT adapt(Call<ResponseT> call, Object[] args) {
      return callAdapter.adapt(call);
    }
    

    callAdapter其实是RxJava3CallAdapter,我们看他的adapt(call)方法

    public Object adapt(Call<R> call) {
    Observable<Response<R>> responseObservable =
        isAsync ? new CallEnqueueObservable<>(call) : new CallExecuteObservable<>(call);
    
    Observable<?> observable;
    if (isResult) {
      observable = new ResultObservable<>(responseObservable);
    } else if (isBody) {
      observable = new BodyObservable<>(responseObservable);
    } else {
      observable = responseObservable;
    }
    
    if (scheduler != null) {
      observable = observable.subscribeOn(scheduler);
    }
    
    if (isFlowable) {
      return observable.toFlowable(BackpressureStrategy.LATEST);
    }
    if (isSingle) {
      return observable.singleOrError();
    }
    if (isMaybe) {
      return observable.singleElement();
    }
    if (isCompletable) {
      return observable.ignoreElements();
    }
    return RxJavaPlugins.onAssembly(observable);
    }
    

    默认情况下isAsync=true,也就是同步方法,会调用CallEnqueueObservable(call),这里的call是OkHttpCall,异步的话,会调用CallExecuteObservable<>(call),其实他们的操作差不多,只是在RealCall时是否会开启线程,接着会生成BodyObservable对象,并return observable,看到没有,已经跟Rxjava结合起来了,如果不懂Rxjava的源码的可以看下我之前写过的Rxjava的源码分析https://www.jianshu.com/p/110ce1b9ff38

    当调用subscirbe()方法时,会调用对应Observable中的subscribeActual(Observer),看CallEnqueueObservable.subscribeActual()

    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);
    if (!callback.isDisposed()) {
      call.enqueue(callback);
    }
    }
    

    这里的call就是OkHttpCall,点进去,

    public void enqueue(final Callback<T> callback) {
    Objects.requireNonNull(callback, "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) {
          throwIfFatal(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) {
            Response<T> response;
            try {
              response = parseResponse(rawResponse);
            } catch (Throwable e) {
              throwIfFatal(e);
              callFailure(e);
              return;
            }
    
            try {
              callback.onResponse(OkHttpCall.this, response);
            } catch (Throwable t) {
              throwIfFatal(t);
              t.printStackTrace(); // TODO this is not great
            }
          }
    
          @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) {
              throwIfFatal(t);
              t.printStackTrace(); // TODO this is not great
            }
          }
        });
    }
    

    会调用createRawCall()方法,

    private okhttp3.Call createRawCall() throws IOException {
    okhttp3.Call call = callFactory.newCall(requestFactory.create(args));
    if (call == null) {
      throw new NullPointerException("Call.Factory returned null.");
    }
    return call;
    }
    

    requestFactory.create(args)会将请求参数封装到okhttp3.Request中

    还记得callFactory吗,没错,这个就是OkHttpClient,看newCall方法,

    public Call newCall(Request request) {
    return RealCall.newRealCall(this, request, false /* for web socket */);
    }
    

    生成的是RealCall,而RealCall就是OkHttp进行网络请求的核心类,所有call就是RealCall,继续往下走, call.enqueue(okhttp3.Callback)网络请求就是OkHttp的东西了,当请求成功时,会回调onResponse方法,

    response = parseResponse(rawResponse);
    
    Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
    ResponseBody rawBody = rawResponse.body();
    
    // Remove the body's source (the only stateful object) so we can pass the response along.
    rawResponse =
        rawResponse
            .newBuilder()
            .body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength()))
            .build();
    
    int code = rawResponse.code();
    if (code < 200 || code >= 300) {
      try {
        // Buffer the entire body to avoid future I/O.
        ResponseBody bufferedBody = Utils.buffer(rawBody);
        return Response.error(bufferedBody, rawResponse);
      } finally {
        rawBody.close();
      }
    }
    
    if (code == 204 || code == 205) {
      rawBody.close();
      return Response.success(null, rawResponse);
    }
    
    ExceptionCatchingResponseBody catchingBody = new ExceptionCatchingResponseBody(rawBody);
    try {
      T body = responseConverter.convert(catchingBody);
      return Response.success(body, rawResponse);
    } catch (RuntimeException e) {
      // If the underlying source threw an exception, propagate that rather than indicating it was
      // a runtime exception.
      catchingBody.throwIfCaught();
      throw e;
    }
    }
    

    这里面会有一些请求码的判断,如果不是200的话,会将rawResponse封装到Response中,并返回,当正常请求成功的情况下,会调用

    T body = responseConverter.convert(catchingBody);
    

    而这里的responseConverter就是GsonResponseBodyConverter对象,这里就是将返回回来的json用Gson序列化

    最后回调到RxJava的CallEnqueueObservable的onResponse中,

    public void onResponse(Call<T> call, Response<T> response) {
      if (disposed) return;
    
      try {
        observer.onNext(response);
    
        if (!disposed) {
          terminated = true;
          observer.onComplete();
        }
      } catch (Throwable t) {
        Exceptions.throwIfFatal(t);
        if (terminated) {
          RxJavaPlugins.onError(t);
        } else if (!disposed) {
          try {
            observer.onError(t);
          } catch (Throwable inner) {
            Exceptions.throwIfFatal(inner);
            RxJavaPlugins.onError(new CompositeException(t, inner));
          }
        }
      }
    }
    

    里面做的事情是将response传递到下游Observable中observer.onNext(response),之后会调用observer.onComplete(),而下游的Observable是BodyObservable,看下里面的Observer里的onNext()方法,

    public void onNext(Response<R> response) {
      if (response.isSuccessful()) {
        observer.onNext(response.body());
      } else {
        terminated = true;
        Throwable t = new HttpException(response);
        try {
          observer.onError(t);
        } catch (Throwable inner) {
          Exceptions.throwIfFatal(inner);
          RxJavaPlugins.onError(new CompositeException(t, inner));
        }
      }
    }
    

    逻辑很简单,只是获取了里面的body。

    还有onFailure()方法回调,其实逻辑是相同的,这里就不在赘述,自此,Retrofit的源码分析已完。

    总结

    可以发现其实Retrofit的源码比较的好理解,跟着代码走就可以了

    相关文章

      网友评论

          本文标题:Retrofit流程分析

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