注册

Retrofit流程极简解析

d2ad46461db04d37b8a790a91d476ce7~tplv-k3u1fbpfcp-zoom-crop-mark:1304:1304:1304:734.awebp?

Retrofit流程极简解析

以SandwichDemo为例子来解析。github地址

创建Retrofit

  • private val retrofit: Retrofit = Retrofit.Builder()
    .client(okHttpClient)
    .baseUrl(
    "https://gist.githubusercontent.com/skydoves/aa3bbbf495b0fa91db8a9e89f34e4873/raw/a1a13d37027e8920412da5f00f6a89c5a3dbfb9a/"
    )
    .addConverterFactory(GsonConverterFactory.create())

    /* asynchronous supports */
    // .addCallAdapterFactory(DataSourceCallAdapterFactory.create())

    /* coroutines supports */
    .addCallAdapterFactory(CoroutinesResponseCallAdapterFactory.create())
    //.addCallAdapterFactory(CoroutinesDataSourceCallAdapterFactory.create())
    .build()

    创建接口类

    val disneyService: DisneyCoroutinesService = retrofit.create(DisneyCoroutinesService::class.java)

    获取接口返回的数据

    val apiResponse:ApiResponse<List<Poster>> = disneyService.fetchDisneyPosterList()

    就是这么简单,数据获取完成


细分流程解析

    1. 创建Retrofit。这里使用了创建者模式,通过Retrofit.Builder来创建Retrfofit实例,一般项目里都会做成单例
    2. Builder().client(OkHttpClient client)设置网络请求的最终调用者,这里和OkHttp是绝配
    3. baseUrl(Url baseUrl)设置baseUrl链接
    4. addConverterFactory(Converter.Factory factory)添加网络参数和返回类的转换器,例如Gson,Moshi
    5. addCallAdapterFactory(CallAdapter.Factory factory)添加接口请求结果的转换器
    6. build()方法中,会通过platform.defaultCallAdapterFactories(callbackExecutor)来添加默认的CallAdapter.Factory转换器和我们自定义的转换器。而ConvertorFactory转换器,默认加入new BuiltInConverters()和平台默认转换器platform.defaultConverterFactories()以及我们自定义的转换器
  • 通过Retrofit创建接口类 1.调用create(Class<T> 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);
    }
    });

    这里就是通过动态代理来。动态代理的理论网上很多,可以自己搜索;简单说下,就是比如代理的接口类,调用它的方法时候,会进入到动态代理类里InvocationHandlerinvoke()中,这里参数有method提供Method的各种方法,args参数提供方法的各个参数。这里就是完全代理了接口方法,来自己实现,这里思想多大,舞台就有多大。

  • invoke方法解析

    1. 解析loadServiceMethod(method).invoke(args)loadServiceMethod()方法返回ServiceMethod抽象类,实际是HttpServiceMethod类。
    2. 核心方法HttpServiceMethod.parseAnnotations方法调用并返回HttpServiceMethod类,这里是核心解析方法;上面的invoke(args)方法最终是调用了HttpServiceMethod类的invoke方法,最终是调用如下:
     @Override
    final @Nullable ReturnT invoke(Object[] args) {
    Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
    return adapt(call, args);
    }

    这里记住这个类OkHttpCall 3. 解析HttpServiceMethod<ResponseT, ReturnT>.parseAnnotations()方法: 这里会通过RequestFactory来解析参数和返回值,其中 java if (Utils.getRawType(parameterType) == Continuation.class) { isKotlinSuspendFunction = true; return null; } 这个解析判断是否是suspend函数。 这里会根据是否挂起函数来确定不同的返回值。 继续:根据是否是挂起函数,来获取对应的adapterType,即类似Call<UserData>里的UserData类型,或者suspendUserData返回值类型。

    CallAdapter<ResponseT, ReturnT> callAdapter =
    createCallAdapter(retrofit, method, adapterType, annotations);
    Type responseType = callAdapter.responseType();

    这里通过返回类型,来匹配我们加入的CallAdapter来进行返回的Response的包装或者逻辑处理

    Converter<ResponseBody, ResponseT> responseConverter =
    createResponseConverter(retrofit, method, responseType);

    这里通过responseType来获取我们添加的返回结果转换器,比如GsonFactory,MothiFactory来 4.

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

    这里会返回最终的各式各样的HttpMethod的实现类 如果非suspend函数,则直接返回CallAdapter这里,Java代码非协程一般都是这种情况; 如果是suspend函数且返回值为Response类型的,则返回SuspendForResponse 其余的suspend函数情况,则返回SuspendForBodykotlin+协程里一般是这种情况 5. 分析CallAdapterSuspendForBody的区别,最大区别,就是Suspend会再adapt里自动调用OkHttp的请求接口方法并返回对应的Response,而CallAdapter则不会,而是需要使用者自己去调用。

    至此,简略版的Retrofit流程已经梳理完毕

    我们自己可以自定义的部分:ConverterFactoryCallFactory这里官方都给了默认的和常用的,例如Converter转换类就有gson,guava,jackson,moshi,jaxb....;而默认的CallFactory,除了库里自带的默认的DefualtCallFactory,还有官方写的库:guava,java8,rxjava,rxjava2,rxjava3,scala,这里常用的是rxjava2,rxjava3,还有例如我现在用的Sandwich库里封装的CoroutinesResponseCallAdapterFactorykotlin协程配合起来非常好用

0 个评论

要回复文章请先登录注册