Retrofit 原理探索

从Retrofit的 create()方法说起。

UserApi userApi = RetrofitFactory.create().create(UserApi.class);

这里指create(UserApi.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.callAdapter.adapt(okHttpCall);
          }
        });
  }
先调用Utils.validateServiceInterface(service); 
static <T> void validateServiceInterface(Class<T> service) {
    if (!service.isInterface()) {
      throw new IllegalArgumentException("API declarations must be interfaces.");
    }
    // Prevent API interfaces from extending other interfaces. This not only avoids a bug in
    // Android (http://b.android.com/58753) but it forces composition of API declarations which is
    // the recommended pattern.
    if (service.getInterfaces().length > 0) {
      throw new IllegalArgumentException("API interfaces must not extend other interfaces.");
    }
  }
这个方法检查传进去的类是不是接口,不是抛出异常,其实retrofit 用了动态带理模式,这里就可以看出来,泛型加接口,这里后面再细说。接着后面就是调用

Proxy.newProxyInstance(ClassLoader loader,
                                      Class<?>[] interfaces,
                                      InvocationHandler h)

这是java 反射相关知识。所以说框架类绝大部分离不开java的三个核心知识点:反射、泛型、注解。这里返回了一个动态带理对象(动态代理不了解点击这里)。关键我们看看第三个参数InvocationHandler ,它用来一个匿名内部类,类中看到 

ServiceMethod<Object, Object> serviceMethod = (ServiceMethod<Object, Object>) loadServiceMethod(method);

点击进去看到

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

这里用map进行缓存,如果之前已经使用过该方法直接从缓存里取,否则进行 new serviceMethod.Builder(this, method).build(); 

这句代码很关键,一看就是builder模式,我们点击进行看一下:


    Builder(Retrofit retrofit, Method method) {
      this.retrofit = retrofit;
      this.method = method;
      this.methodAnnotations = method.getAnnotations();
      this.parameterTypes = method.getGenericParameterTypes();
      this.parameterAnnotationsArray = method.getParameterAnnotations();
    }

    public ServiceMethod build() {
      callAdapter = createCallAdapter();
      responseType = callAdapter.responseType();
      if (responseType == Response.class || responseType == okhttp3.Response.class) {
        throw methodError("'"
            + Utils.getRawType(responseType).getName()
            + "' is not a valid response body type. Did you mean ResponseBody?");
      }
      responseConverter = createResponseConverter();

      for (Annotation annotation : methodAnnotations) {
        parseMethodAnnotation(annotation);
      }

    ......
 int parameterCount = parameterAnnotationsArray.length;
      parameterHandlers = new ParameterHandler<?>[parameterCount];
      for (int p = 0; p < parameterCount; p++) {
        Type parameterType = parameterTypes[p];
        if (Utils.hasUnresolvableType(parameterType)) {
          throw parameterError(p, "Parameter type must not include a type variable or wildcard: %s",
              parameterType);
        }

        Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
        if (parameterAnnotations == null) {
          throw parameterError(p, "No Retrofit annotation found.");
        }

        parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
      }

      if (relativeUrl == null && !gotUrl) {
        throw methodError("Missing either @%s URL or @Url parameter.", httpMethod);
      }
      if (!isFormEncoded && !isMultipart && !hasBody && gotBody) {
        throw methodError("Non-body HTTP method cannot contain @Body.");
      }
      if (isFormEncoded && !gotField) {
        throw methodError("Form-encoded method must contain at least one @Field.");
      }
      if (isMultipart && !gotPart) {
        throw methodError("Multipart method must contain at least one @Part.");
      }

      return new ServiceMethod<>(this);
    }

先是构建自己,然后在build()方法中去进行转换器、callAdapter 赋值操作,同时,进行注解解析等等操作,最后拿到CallAdapter对象,而okHttp和RxJava 都有相应的实现OkhttpCall ,Rxjava2CallAdapter ; 分别去配合retrofit的使用,这里为止就是Retrofit的全部了。 所以在build.gradle 文件中要使用 

implementation 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'

依赖,同时也说说

为什么RxJava和Retrofit 可以结合使用?

因为 在构建Retrofit 对象的时候我们给他添加了一个Rxjava的callAdapter ,

 mDefaultBuilder = new Retrofit.Builder()
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create());

就是因为这个东西把retrofit 通过okhttp请求回来的数据转化成了 Observable , 老规矩分析一下,如何转换的?

先看看没有用RxJava 时,如何使用Okhttp 结合 Retrofit ?

 // 1. 创建 网络请求接口 的实例
        GetRequest_Interface request = retrofit.create(GetRequest_Interface.class);

        // 2. 采用Call<..>接口 对 发送请求 进行封装
        Call<Translation> call = request.getCall();

        // 3. 发送网络请求(异步)
        call.enqueue(new Callback<Translation>() {
            // 请求成功时回调
            @Override
            public void onResponse(Call<Translation> call, Response<Translation> response) {
                 ...  
            }

            // 请求失败时回调
            @Override
            public void onFailure(Call<Translation> call, Throwable throwable) {
                ....
            }
        });

第二步返回的是一个Call 对象没有写出Obserable数据流形式(因为他会用默认的Retrofit自带的CallAdapter)。 回到之前的代码call 进行真正的网络请求。我们还记得  

serviceMethod.callAdapter.adapt(okHttpCall)

这句代码,点击adapt方法,他是一个 泛型接口

T adapt(Call<R> call)

,然后由于我们用了是Rxjava的callAdapter,所以它去用rxjava中的实现,看一下rxjava的实现

 @Override 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 observable;
  }

由于异步会执行CallEnqueueObserable ,而其又是继承Observable ,这样RxJava和Retrofit就联系起来了,同时通过接口我们就能得到Obserable 数据流了。至于 CallEnqueueObserable 内部的逻辑就不去深究了。

final class CallEnqueueObservable<T> extends Observable<Response<T>>

猜你喜欢

转载自blog.csdn.net/sjh_389510506/article/details/88765224