Retrofit 原理

Retrofit 是对 OkHttp 网络库的封装,真正的网络请求是通过 OkHttp 完成的

Retrofit 涉及到的设计模式

构建模式、代理模式、工厂模式、适配器模式

源码分析要点

  • 使用构建模式创建 Retrofit 实例对象
  • 使用代理模式创建网络请求接口的代理类
  • 解析网络接口的注解,生成 ServiceMethod 对象
  • 通过工厂模式及 Method 信息生成网络请求适配器和内容解析器
  • 通过适配器模式适配 Call 接口,并返回对应的类型(Completable、Deferred)
  • 网络结果返回时,在 ServiceMethod#toResponse 方法中通过解析器生成具体的返回值

使用 Retrofit 时,需要先创建一个 Retrofit 实例

private fun createRetrofit(): Retrofit {
    val retrofit = Retrofit.Builder()
            .client(buildOkHttp(builder))
            .baseUrl(buildUrl())
            .addInterceptor(XXXInterceptor())
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
            .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke())
            .addConverterFactory(WireConverterFactory.create())
            .addConverterFactory(GsonConverterFactory.create())
    return retrofit.build()
}

Retrofit.Builder 的 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();
  }

  // 请求适配器工厂类,并添加默认的请求适配器工厂类
  List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
  adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));

  // 内容解析器工厂类
  List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);

  return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
      callbackExecutor, validateEagerly);
}

Retrofit 的 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) {
            // 对网络请求方法进行包装生成ServiceMethod
            ServiceMethod<Object, Object> serviceMethod = loadServiceMethod(method);
            // 生成网络请求对象
            OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
            // 通过 adapt 方法进行网络请求
            return serviceMethod.callAdapter.adapt(okHttpCall);
        }
    });
}

ServiceMethod 的 build 方法

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

public ServiceMethod build() {
    // 遍历工厂类,根据 Method 的返回值类型决定采用那个 Adapter,
    // 如果是String、Int等则采用默认提供的 Adapter,如果是 Completable<T>,则采用RxjavaAdapter
    callAdapter = createCallAdapter();
    responseType = callAdapter.responseType();
    // 遍历内容解析器工厂类,根据 responseType 来决定采用那个解析器,
    // 比如Response继承了 Message,则 WireConverterFactory 会返回 WireResponseBodyConverter
    responseConverter = createResponseConverter();

    for (Annotation annotation : methodAnnotations) {
        parseMethodAnnotation(annotation);
    }
    return new ServiceMethod<>(this);
}

这里假设我们采用了RxJava2CallAdapter请求适配器,直接看 adapt 实现,通过适配器模式,直接通过CallExecuteObservable封装了call.execute请求

public <R1> R adapt(Call<R1> call) {
    Observable<SsResponse<R1>> 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 (R) observable.toFlowable(BackpressureStrategy.LATEST)
                    .retryWhen(new RetryWhenPublisherHandler(retryCount));
    }
    if (isSingle) {
        return (R) observable.singleOrError()
                    .retryWhen(new RetryWhenPublisherHandler(retryCount));
    }
    if (isMaybe) {
        return (R) observable.singleElement()
                    .retryWhen(new RetryWhenPublisherHandler(retryCount));
    }
    if (isCompletable) {
        return (R) observable.ignoreElements()
                    .retryWhen(new RetryWhenPublisherHandler(retryCount));
    }
    return (R) RxJavaPlugins.onAssembly(observable)
                    .retryWhen(new RetryWhenHandler(retryCount));
}

OkHttpCall.execute -> OkHttpCall.parseResponse -> serviceMethod.toResponse

@Override public Response<T> execute() throws IOException {
    okhttp3.Call call;

    synchronized (this) {
        if (executed) throw new IllegalStateException("Already executed.");
        executed = true;

        if (creationFailure != null) {
            if (creationFailure instanceof IOException) {
                throw (IOException) creationFailure;
            } else {
                throw (RuntimeException) creationFailure;
            }
        }

        call = rawCall;
        if (call == null) {
            try {
                call = rawCall = createRawCall();
            } catch (IOException | RuntimeException e) {
                creationFailure = e;
                throw e;
            }
        }
    }
    // 最终调用 内容解析器 解析,然后该方法返回值返回给 网络适配器,并通过RxJava发射出去
    return parseResponse(call.execute());
}

Interceptor 经典用法

Passport Sdk 会提供 TTTokenInterceptor,用于自动处理 request 和 response,用于从 response中提取鉴权信息并在 header 中添加身份鉴权信息

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

little-sparrow

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值