retrofit系列-ServiceMethod创建流程

1.使用retrofit的例子 

  • 创建一个interface RetrofitServiceApi
public interface RetrofitServiceApi {
    @POST("/user/get/userinfo")
    Call> requestUserInfo(@Query("token") String token);
}
  • 调用Retrofit的create方法来创建 RetrofitServiceApi对象后,调用requestUserInfo方法
//调用RetrofitServiceApi的requestUserInfo方法

public Call> requestUserInfo(String token) {
    return mRetrofit.create(RetrofitServiceApi.class).requestUserInfo(token);
}

 2.Retrofit.create

  • 调用Proxy.nexProxyInstance创建动态代理对象
  • 调用参数的service的方法的时候,会触发invoke方法的执行
//retrofit\src\main\java\retrofit2\Retrofit.java

public final class Retrofit {

    public  T create(final Class service) {
        validateServiceInterface(service); //判断是不是接口,不是的话就抛出异常

        return (T)
            Proxy.newProxyInstance(
                service.getClassLoader(),
                new Class[] {service},
                new InvocationHandler() {
                    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.
                        //获取声明该方法的类的 Class 对象
                        if (method.getDeclaringClass() == Object.class) {
                            return method.invoke(this, args);
                        }
                        args = args != null ? args : emptyArgs;
                        Platform platform = Platform.get();
                        return platform.isDefaultMethod(method)
                             ? platform.invokeDefaultMethod(method, service, proxy, args)
                             : loadServiceMethod(method).invoke(args);
                    }
            });
    }
}

3.Retrofit.loadServiceMethod

先从缓存里获取ServiceMethod

        找到,返回结果;

        没找到,调用ServiceMethod.parseAnnotations创建ServiceMethod后,放入缓存,返回结果;

 

 retrofit系列-ServiceMethod创建流程_第1张图片

public final class Retrofit {
    private final Map> serviceMethodCache = new 
                ConcurrentHashMap<>();    

    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); //生成ServiceMethod
                serviceMethodCache.put(method, result);//放入方法缓存
            }
        }
        return result;
    }
}

4.ServiceMethod.parseAnnotations 创建ServiceMethod

//retrofit\src\main\java\retrofit2\ServiceMethod.java

abstract class ServiceMethod {
    static  ServiceMethod parseAnnotations(Retrofit retrofit, Method method) {
        //4.1
        RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);

        //省略部分代码

        //4.2
        return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
    }
}
4.1.RequestFactory.parseAnnotations
//retrofit\src\main\java\retrofit2\RequestFactory.java

final class RequestFactory {
    //所以一个Method对应一个RequestFactory
    static RequestFactory parseAnnotations(Retrofit retrofit, Method method) {
        return new Builder(retrofit, method).build();
    }
}
 4.1.1.new Builder
//retrofit\src\main\java\retrofit2\RequestFactory.java

final class RequestFactory {
    
    static final class Builder {
        final Annotation[] methodAnnotations;
        final Annotation[][] parameterAnnotationsArray;

        Builder(Retrofit retrofit, Method method) {
            this.retrofit = retrofit;
            this.method = method;
            this.methodAnnotations = method.getAnnotations();
            this.parameterTypes = method.getGenericParameterTypes();
            this.parameterAnnotationsArray = method.getParameterAnnotations();
        }
    }
}
4.1.2.build
//retrofit\src\main\java\retrofit2\RequestFactory.java

final class RequestFactory {
    
    static final class Builder {

        RequestFactory build() {
            for (Annotation annotation : methodAnnotations) {
                parseMethodAnnotation(annotation); //4.1.2.1
            }

            //省略部分代码

            return new RequestFactory(this);
        }
    }
}
4.1.2.1.parseMethodAnnotation

根据annotation来确定调用parseHttpMethodAndPath方法时各个参数的值

//retrofit\src\main\java\retrofit2\RequestFactory.java
final class RequestFactory {
    static final class Builder {
        private void parseMethodAnnotation(Annotation annotation) {
            //省略部分代码
            if (annotation instanceof POST) {
                parseHttpMethodAndPath("POST", ((POST) annotation).value(), true);
            }
        }
    }
}
//retrofit\src\main\java\retrofit2\RequestFactory.java
final class RequestFactory {

    static final class Builder {
        @Nullable String httpMethod;
        boolean hasBody;
        @Nullable String relativeUrl;
        @Nullable Set relativeUrlParamNames;

        private void parseHttpMethodAndPath(String httpMethod, String value, boolean 
            hasBody){
            this.httpMethod = httpMethod;
            this.hasBody = hasBody;

            if (value.isEmpty()) { //上面例子的value是""
                return;
            }

            //如果不是"",会继续解析URL参数
            this.relativeUrl = value;
            this.relativeUrlParamNames = parsePathParameters(value);
        }

        static Set parsePathParameters(String path) {
            Matcher m = PARAM_URL_REGEX.matcher(path);
            Set patterns = new LinkedHashSet<>();
            while (m.find()) {
                patterns.add(m.group(1));
            }
            return patterns;
        }
    }
}
4.2.HttpServiceMethod.parseAnnotations
abstract class HttpServiceMethod extends ServiceMethod {
    static  HttpServiceMethod parseAnnotations(
      Retrofit retrofit, Method method, RequestFactory requestFactory) {
        //1.创建CallAdapter
        CallAdapter callAdapter =
            createCallAdapter(retrofit, method, adapterType, annotations);
        //2.创建Converter
        Converter responseConverter =
            createResponseConverter(retrofit, method, responseType);

        okhttp3.Call.Factory callFactory = retrofit.callFactory;

        //创建HttpServiceMethod
        if (!isKotlinSuspendFunction) {
            return new CallAdapted<>(requestFactory, callFactory, responseConverter, 
                 callAdapter);
        } else if (continuationWantsResponse) {
            //noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
            return (HttpServiceMethod)
                new SuspendForResponse<>(
                    requestFactory,
                    callFactory,
                    responseConverter,
                    (CallAdapter>) callAdapter);
        } else {
            //noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
            return (HttpServiceMethod)
                new SuspendForBody<>(
                    requestFactory,
                    callFactory,
                    responseConverter,
                    (CallAdapter>) callAdapter,
                    continuationBodyNullable,
                    continuationIsUnit);
        }
    }
}
4.3.CallAdapted、SuspendForResponse、SuspendForBody 的区别

在 Retrofit 中,`CallAdapted`、`SuspendForResponse` 和 `SuspendForBody` 主要涉及到 Retrofit 如何处理异步调用和响应处理。

CallAdapted:

  • `CallAdapted` 通常指的是标准的同步 Retrofit 调用。
  • 它表示以同步方式执行的调用,这意味着调用在当前线程上进行,并且会一直阻塞,直到收到响应。
  • 这是使用 Retrofit 进行 API 调用的传统方式。

SuspendForResponse:

  • `SuspendForResponse` 表示一个挂起函数,用于处理异步调用,该函数的返回类型是 `Response`,其中 `T` 是 API 响应的类型。
  • 使用挂起函数可以更方便地在异步环境中处理响应,而无需使用回调或其他异步编程模式。

SuspendForBody:

  • `SuspendForBody` 也是一个挂起函数,但是它的返回类型是 `T`,即 API 响应的实际数据类型。
  • 这种方式更关注处理响应体的内容,而不是完整的响应对象。

总体而言,这些类型主要用于在 Retrofit 中以同步或异步的方式处理 API 调用和响应。`SuspendForResponse` 和 `SuspendForBody` 是与 Kotlin 挂起函数一起使用的,使得在异步场景中更容易进行处理。

你可能感兴趣的:(retrofit,retrofit)