Android Retrofit 框架的接口代理与调用模块源码分析(二)

发布于:2025-03-12 ⋅ 阅读:(18) ⋅ 点赞:(0)

一、引言

在 Android 开发中,网络请求是必不可少的一部分。Retrofit 作为一个广泛使用的类型安全的 HTTP 客户端,极大地简化了网络请求的操作。其核心在于接口代理与调用模块,它将接口方法的调用巧妙地转化为实际的 HTTP 请求,并处理响应结果。本文将深入 Retrofit 框架的源码,详细剖析接口代理与调用模块的实现细节。

二、Retrofit 基本使用回顾

在深入源码之前,先简单回顾一下 Retrofit 的基本使用:

java

// 定义 API 接口
public interface GitHubService {
    // 使用 GET 请求获取用户信息
    @GET("users/{user}")
    Call<ResponseBody> getUser(@Path("user") String user);
}

// 创建 Retrofit 实例
Retrofit retrofit = new Retrofit.Builder()
       .baseUrl("https://api.github.com/")
       .build();

// 创建 API 接口的代理对象
GitHubService service = retrofit.create(GitHubService.class);

// 调用接口方法
Call<ResponseBody> call = service.getUser("octocat");
// 执行异步请求
call.enqueue(new Callback<ResponseBody>() {
    @Override
    public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
        // 处理响应结果
    }

    @Override
    public void onFailure(Call<ResponseBody> call, Throwable t) {
        // 处理请求失败
    }
});

从上述代码可以看出,使用 Retrofit 进行网络请求主要分为以下几个步骤:定义 API 接口、创建 Retrofit 实例、创建接口代理对象、调用接口方法和执行请求。下面我们将逐步深入这些步骤背后的源码实现。

三、Retrofit 实例创建

3.1 Retrofit.Builder 类

Retrofit 实例的创建通常使用 Retrofit.Builder 类,该类提供了一系列的配置方法。以下是 Retrofit.Builder 类的部分源码:

java

public static final class Builder {
    // OkHttp 的请求工厂,用于创建实际的 HTTP 请求
    private okhttp3.Call.Factory callFactory;
    // 基础 URL
    private HttpUrl baseUrl;
    // 调用适配器工厂列表,用于将网络请求结果适配为不同的类型
    private final List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>();
    // 转换器工厂列表,用于将请求参数和响应结果进行序列化和反序列化
    private final List<Converter.Factory> converterFactories = new ArrayList<>();
    // 回调执行器,用于将回调切换到指定线程
    private Executor callbackExecutor;
    // 是否验证服务接口
    private boolean validateEagerly;

    public Builder() {
        // 默认使用 OkHttpClient 作为请求工厂
        this(Platform.get());
    }

    Builder(Platform platform) {
        // 添加默认的调用适配器工厂
        callAdapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
    }

    // 设置请求工厂
    public Builder callFactory(okhttp3.Call.Factory factory) {
        this.callFactory = checkNotNull(factory, "factory == null");
        return this;
    }

    // 设置基础 URL
    public Builder baseUrl(String baseUrl) {
        checkNotNull(baseUrl, "baseUrl == null");
        return baseUrl(HttpUrl.get(baseUrl));
    }

    public Builder baseUrl(HttpUrl baseUrl) {
        checkNotNull(baseUrl, "baseUrl == null");
        List<String> pathSegments = baseUrl.pathSegments();
        if (!"".equals(pathSegments.get(pathSegments.size() - 1))) {
            throw new IllegalArgumentException("baseUrl must end in /: " + baseUrl);
        }
        this.baseUrl = baseUrl;
        return this;
    }

    // 添加调用适配器工厂
    public Builder addCallAdapterFactory(CallAdapter.Factory factory) {
        callAdapterFactories.add(checkNotNull(factory, "factory == null"));
        return this;
    }

    // 添加转换器工厂
    public Builder addConverterFactory(Converter.Factory factory) {
        converterFactories.add(checkNotNull(factory, "factory == null"));
        return this;
    }

    // 设置回调执行器
    public Builder callbackExecutor(Executor executor) {
        this.callbackExecutor = checkNotNull(executor, "executor == null");
        return this;
    }

    // 是否验证服务接口
    public Builder validateEagerly(boolean validateEagerly) {
        this.validateEagerly = validateEagerly;
        return this;
    }

    // 构建 Retrofit 实例
    public Retrofit build() {
        if (baseUrl == null) {
            throw new IllegalStateException("Base URL required.");
        }

        okhttp3.Call.Factory callFactory = this.callFactory;
        if (callFactory == null) {
            // 如果没有设置请求工厂,使用默认的 OkHttpClient
            callFactory = new OkHttpClient();
        }

        Executor callbackExecutor = this.callbackExecutor;
        if (callbackExecutor == null) {
            // 如果没有设置回调执行器,使用平台默认的执行器
            callbackExecutor = Platform.get().defaultCallbackExecutor();
        }

        // 复制调用适配器工厂列表,并添加默认的调用适配器工厂
        List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
        callAdapterFactories.addAll(Platform.get().defaultCallAdapterFactories(callbackExecutor));

        // 复制转换器工厂列表,并添加默认的转换器工厂
        List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);
        converterFactories.add(0, new BuiltInConverters());

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

Retrofit.Builder 类的主要作用是配置 Retrofit 实例的各种参数,包括请求工厂、基础 URL、调用适配器工厂、转换器工厂和回调执行器等。在 build() 方法中,会对这些参数进行检查和默认值的设置,最终创建一个 Retrofit 实例。

3.2 Retrofit 类

Retrofit 类是 Retrofit 框架的核心类,它封装了各种配置信息,并提供了创建接口代理对象的方法。以下是 Retrofit 类的部分源码:

java

public final class Retrofit {
    // OkHttp 的请求工厂
    private final okhttp3.Call.Factory callFactory;
    // 基础 URL
    private final HttpUrl baseUrl;
    // 转换器工厂列表
    private final List<Converter.Factory> converterFactories;
    // 调用适配器工厂列表
    private final List<CallAdapter.Factory> callAdapterFactories;
    // 回调执行器
    private final Executor callbackExecutor;
    // 服务方法缓存
    private final Map<Method, ServiceMethod<?, ?>> serviceMethodCache = new ConcurrentHashMap<>();
    // 是否验证服务接口
    private final boolean validateEagerly;

    Retrofit(okhttp3.Call.Factory callFactory, HttpUrl baseUrl,
             List<Converter.Factory> converterFactories, List<CallAdapter.Factory> callAdapterFactories,
             Executor callbackExecutor, boolean validateEagerly) {
        this.callFactory = callFactory;
        this.baseUrl = baseUrl;
        this.converterFactories = unmodifiableList(converterFactories);
        this.callAdapterFactories = unmodifiableList(callAdapterFactories);
        this.callbackExecutor = callbackExecutor;
        this.validateEagerly = validateEagerly;

        if (validateEagerly) {
            // 如果需要验证服务接口,遍历所有方法并加载服务方法
            eagerlyValidateMethods();
        }
    }

    // 获取请求工厂
    public okhttp3.Call.Factory callFactory() {
        return callFactory;
    }

    // 获取基础 URL
    public HttpUrl baseUrl() {
        return baseUrl;
    }

    // 获取转换器工厂列表
    public List<Converter.Factory> converterFactories() {
        return converterFactories;
    }

    // 获取调用适配器工厂列表
    public List<CallAdapter.Factory> callAdapterFactories() {
        return callAdapterFactories;
    }

    // 获取回调执行器
    public Executor callbackExecutor() {
        return callbackExecutor;
    }

    // 创建 API 接口的代理对象
    public <T> T create(final Class<T> service) {
        // 验证传入的 service 是否为接口类型
        validateServiceInterface(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, Object[] args)
                            throws Throwable {
                        // 如果调用的是 Object 类的方法,直接调用
                        if (method.getDeclaringClass() == Object.class) {
                            return method.invoke(this, args);
                        }
                        // 如果是默认方法,根据平台进行处理
                        if (platform.isDefaultMethod(method)) {
                            return platform.invokeDefaultMethod(method, service, proxy, args);
                        }
                        // 创建 ServiceMethod 对象
                        ServiceMethod<Object, Object> serviceMethod =
                                (ServiceMethod<Object, Object>) loadServiceMethod(method);
                        // 创建 OkHttpCall 对象
                        OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
                        // 通过 CallAdapter 进行适配
                        return serviceMethod.callAdapter.adapt(okHttpCall);
                    }
                });
    }

    // 加载服务方法
    ServiceMethod<?, ?> loadServiceMethod(Method method) {
        // 从缓存中获取 ServiceMethod 对象
        ServiceMethod<?, ?> result = serviceMethodCache.get(method);
        if (result != null) return result;

        synchronized (serviceMethodCache) {
            // 再次从缓存中获取 ServiceMethod 对象
            result = serviceMethodCache.get(method);
            if (result == null) {
                // 如果缓存中没有,则创建一个新的 ServiceMethod 对象
                result = ServiceMethod.parseAnnotations(this, method);
                // 将新创建的 ServiceMethod 对象放入缓存中
                serviceMethodCache.put(method, result);
            }
        }
        return result;
    }

    // 提前验证服务接口的方法
    private void eagerlyValidateMethods() {
        Platform platform = Platform.get();
        for (Method method : getClass().getDeclaredMethods()) {
            if (!platform.isDefaultMethod(method) && !Modifier.isStatic(method.getModifiers())) {
                loadServiceMethod(method);
            }
        }
    }
}

Retrofit 类的主要作用是封装配置信息,并提供 create() 方法用于创建 API 接口的代理对象。在 create() 方法中,会使用 Java 的动态代理机制创建一个实现了指定 API 接口的代理对象,并在 InvocationHandlerinvoke() 方法中处理接口方法的调用。

四、接口代理对象的创建

4.1 create() 方法

create() 方法是创建接口代理对象的核心方法,以下是该方法的详细分析:

java

public <T> T create(final Class<T> service) {
    // 验证传入的 service 是否为接口类型
    validateServiceInterface(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, Object[] args)
                        throws Throwable {
                    // 如果调用的是 Object 类的方法,直接调用
                    if (method.getDeclaringClass() == Object.class) {
                        return method.invoke(this, args);
                    }
                    // 如果是默认方法,根据平台进行处理
                    if (platform.isDefaultMethod(method)) {
                        return platform.invokeDefaultMethod(method, service, proxy, args);
                    }
                    // 创建 ServiceMethod 对象
                    ServiceMethod<Object, Object> serviceMethod =
                            (ServiceMethod<Object, Object>) loadServiceMethod(method);
                    // 创建 OkHttpCall 对象
                    OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
                    // 通过 CallAdapter 进行适配
                    return serviceMethod.callAdapter.adapt(okHttpCall);
                }
            });
}

create() 方法的主要步骤如下:

  1. 验证接口类型:调用 validateServiceInterface() 方法验证传入的 service 是否为接口类型。

  2. 使用动态代理创建代理对象:使用 Java 的动态代理机制创建一个实现了指定 API 接口的代理对象。

  3. 实现 InvocationHandler 接口:在 invoke() 方法中处理接口方法的调用。

    • 如果调用的是 Object 类的方法,直接调用该方法。
    • 如果是接口的默认方法,根据平台进行处理。
    • 调用 loadServiceMethod() 方法创建 ServiceMethod 对象。
    • 使用 ServiceMethod 对象和方法参数创建 OkHttpCall 对象。
    • 调用 serviceMethod.callAdapter.adapt() 方法对 OkHttpCall 对象进行适配。

4.2 validateServiceInterface() 方法

validateServiceInterface() 方法用于验证传入的 service 是否为接口类型,并且检查接口方法是否符合 Retrofit 的要求。以下是该方法的源码:

java

private void validateServiceInterface(Class<?> service) {
    // 检查传入的 service 是否为接口类型
    if (!service.isInterface()) {
        throw new IllegalArgumentException("API declarations must be interfaces.");
    }
    // 检查接口是否有默认方法,并且平台是否支持默认方法
    if (Platform.get().isDefaultMethodProblematic()) {
        for (Method method : service.getDeclaredMethods()) {
            if (Platform.get().isDefaultMethod(method)) {
                throw new IllegalArgumentException(
                        "@SkipCallbackExecutor annotation is required on methods "
                                + "with default implementations when targeting API 24 and lower due "
                                + "to an issue with default method dispatch.");
            }
        }
    }
}

该方法主要检查传入的 service 是否为接口类型,并且在某些平台下检查接口是否有默认方法。

4.3 loadServiceMethod() 方法

loadServiceMethod() 方法用于创建 ServiceMethod 对象,该对象封装了 API 接口方法的元数据。以下是该方法的源码:

java

ServiceMethod<?, ?> loadServiceMethod(Method method) {
    // 从缓存中获取 ServiceMethod 对象
    ServiceMethod<?, ?> result = serviceMethodCache.get(method);
    if (result != null) return result;

    synchronized (serviceMethodCache) {
        // 再次从缓存中获取 ServiceMethod 对象
        result = serviceMethodCache.get(method);
        if (result == null) {
            // 如果缓存中没有,则创建一个新的 ServiceMethod 对象
            result = ServiceMethod.parseAnnotations(this, method);
            // 将新创建的 ServiceMethod 对象放入缓存中
            serviceMethodCache.put(method, result);
        }
    }
    return result;
}

loadServiceMethod() 方法首先从缓存中获取 ServiceMethod 对象,如果缓存中没有,则调用 ServiceMethod.parseAnnotations() 方法创建一个新的 ServiceMethod 对象,并将其放入缓存中。

4.4 ServiceMethod.parseAnnotations() 方法

ServiceMethod.parseAnnotations() 方法用于解析 API 接口方法的注解,创建 ServiceMethod 对象。以下是该方法的详细源码和分析:

java

static <T, R> ServiceMethod<T, R> parseAnnotations(Retrofit retrofit, Method method) {
    // 创建 RequestFactory 对象,用于解析请求相关的注解
    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.");
    }

    // 获取 CallAdapter 对象,用于适配网络请求的结果
    CallAdapter<T, R> callAdapter = createCallAdapter(retrofit, method, returnType);
    // 获取响应类型
    Type responseType = callAdapter.responseType();
    if (Utils.hasUnresolvableType(responseType)) {
        throw methodError(method, "Call adapter returned a type that contains wildcards: %s",
                responseType);
    }

    // 获取 Converter 对象,用于将响应结果进行反序列化
    Converter<ResponseBody, T> responseConverter =
            createResponseConverter(retrofit, method, responseType);

    // 获取 OkHttp 的请求工厂
    okhttp3.Call.Factory callFactory = retrofit.callFactory;
    return new ServiceMethod<>(requestFactory, callAdapter, responseConverter, callFactory);
}

// 创建 CallAdapter 对象
private static <T, R> CallAdapter<T, R> createCallAdapter(Retrofit retrofit, Method method, Type returnType) {
    Annotation[] annotations = method.getAnnotations();
    try {
        // 遍历调用适配器工厂列表,查找合适的 CallAdapter 工厂
        for (CallAdapter.Factory factory : retrofit.callAdapterFactories()) {
            CallAdapter<?, ?> adapter = factory.get(returnType, annotations, retrofit);
            if (adapter != null) {
                // 找到合适的 CallAdapter 工厂,返回其创建的 CallAdapter 对象
                return (CallAdapter<T, R>) adapter;
            }
        }
    } catch (RuntimeException e) {
        throw methodError(method, e, "Unable to create call adapter for %s", returnType);
    }
    throw methodError(method, "Could not locate call adapter for %s.", returnType);
}

// 创建响应转换器对象
private static <T> Converter<ResponseBody, T> createResponseConverter(Retrofit retrofit, Method method, Type responseType) {
    Annotation[] annotations = method.getAnnotations();
    try {
        // 遍历转换器工厂列表,查找合适的 Converter 工厂
        for (Converter.Factory factory : retrofit.converterFactories()) {
            Converter<ResponseBody, ?> converter = factory.responseBodyConverter(responseType, annotations, retrofit);
            if (converter != null) {
                // 找到合适的 Converter 工厂,返回其创建的 Converter 对象
                return (Converter<ResponseBody, T>) converter;
            }
        }
    } catch (RuntimeException e) {
        throw methodError(method, e, "Unable to create converter for %s", responseType);
    }
    throw methodError(method, "Could not locate response converter for %s.", responseType);
}

ServiceMethod.parseAnnotations() 方法的主要步骤如下:

  1. 创建 RequestFactory 对象:调用 RequestFactory.parseAnnotations() 方法解析请求相关的注解,创建 RequestFactory 对象。
  2. 获取方法的返回类型:通过 method.getGenericReturnType() 方法获取方法的返回类型,并进行合法性检查。
  3. 获取 CallAdapter 对象:调用 createCallAdapter() 方法,遍历调用适配器工厂列表,查找合适的 CallAdapter 工厂,并返回其创建的 CallAdapter 对象。
  4. 获取响应类型:通过 callAdapter.responseType() 方法获取响应类型,并进行合法性检查。
  5. 获取 Converter 对象:调用 createResponseConverter() 方法,遍历转换器工厂列表,查找合适的 Converter 工厂,并返回其创建的 Converter 对象。
  6. 创建 ServiceMethod 对象:将上述对象作为参数创建 ServiceMethod 对象。

4.5 RequestFactory.parseAnnotations() 方法

RequestFactory.parseAnnotations() 方法用于解析 API 接口方法的请求相关注解,创建 RequestFactory 对象。以下是该方法的详细源码和分析:

java

static RequestFactory parseAnnotations(Retrofit retrofit, Method method) {
    // 创建 RequestFactory.Builder 对象
    return new Builder(retrofit, method).build();
}

// RequestFactory.Builder 类
static final class Builder {
    private final Retrofit retrofit;
    private final Method method;
    private final Annotation[] methodAnnotations;
    private final Annotation[][] parameterAnnotationsArray;
    private final Type[] parameterTypes;
    private HttpUrl baseUrl;
    private String httpMethod;
    private boolean hasBody;
    private boolean isFormEncoded;
    private boolean isMultipart;
    private String relativeUrl;
    private ParameterHandler<?>[] parameterHandlers;

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

    RequestFactory build() {
        // 解析方法注解
        for (Annotation annotation : methodAnnotations) {
            parseMethodAnnotation(annotation);
        }

        if (httpMethod == null) {
            throw methodError(method, "HTTP method annotation is required (e.g., @GET, @POST, etc.).");
        }

        // 解析参数注解
        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(method, p, "Parameter type must not include a type variable or wildcard: %s",
                        parameterType);
            }

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

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

        if (relativeUrl == null && !hasBody) {
            throw methodError(method, "Non-body HTTP method cannot contain @Body.");
        }

        if (isFormEncoded && isMultipart) {
            throw methodError(method, "Only one encoding annotation is allowed.");
        }

        return new RequestFactory(this);
    }

    private void parseMethodAnnotation(Annotation annotation) {
        if (annotation instanceof GET) {
            parseHttpMethodAndPath("GET", ((GET) annotation).value(), false);
        } else if (annotation instanceof POST) {
            parseHttpMethodAndPath("POST", ((POST) annotation).value(), true);
        } else if (annotation instanceof PUT) {
            parseHttpMethodAndPath("PUT", ((PUT) annotation).value(), true);
        } else if (annotation instanceof DELETE) {
            parseHttpMethodAndPath("DELETE", ((DELETE) annotation).value(), false);
        } else if (annotation instanceof HEAD) {
            parseHttpMethodAndPath("HEAD", ((HEAD) annotation).value(), false);
            if (hasBody) {
                throw methodError(method, "@HEAD method must not have a request body.");
            }
        } else if (annotation instanceof PATCH) {
            parseHttpMethodAndPath("PATCH", ((PATCH) annotation).value(), true);
        } else if (annotation instanceof OPTIONS) {
            parseHttpMethodAndPath("OPTIONS", ((OPTIONS) annotation).value(), false);
        } else if (annotation instanceof HTTP) {
            HTTP http = (HTTP) annotation;
            parseHttpMethodAndPath(http.method(), http.path(), http.hasBody());
        } else if (annotation instanceof retrofit2.http.Headers) {
            String[] headersToParse = ((retrofit2.http.Headers) annotation).value();
            if (headersToParse.length == 0) {
                throw methodError(method, "@Headers annotation is empty.");
            }
            headers = parseHeaders(headersToParse);
        } else if (annotation instanceof Multipart) {
            if (isFormEncoded) {
                throw methodError(method, "Only one encoding annotation is allowed.");
            }
            isMultipart = true;
        } else if (annotation instanceof FormUrlEncoded) {
            if (isMultipart) {
                throw methodError(method, "Only one encoding annotation is allowed.");
            }
            isFormEncoded = true;
        }
    }

    private void parseHttpMethodAndPath(String httpMethod, String value, boolean hasBody) {
        if (this.httpMethod != null) {
            throw methodError(method, "Only one HTTP method is allowed. Found: %s and %s.",
                    this.httpMethod, httpMethod);
        }
        this.httpMethod = httpMethod;
        this.hasBody = hasBody;

        if (value.isEmpty()) {
            return;
        }

        // Get the relative URL path and existing query string, if present.
        int question = value.indexOf('?');
        if (question != -1 && question < value.length() - 1) {
            // Ensure the query string does not have any named parameters.
            String queryParams = value.substring(question + 1);
            Matcher queryParamMatcher = PARAM_URL_REGEX.matcher(queryParams);
            if (queryParamMatcher.find()) {
                throw methodError(method, "URL query string "%s" must not have replace block. "
                        + "For dynamic query parameters use @Query.", queryParams);
            }
        }

        this.relativeUrl = value;
        this.relativeUrlParamNames = parsePathParameters(value);
    }

    private ParameterHandler<?> parseParameter(
            int p, Type parameterType, Annotation[] annotations) {
        ParameterHandler<?> result = null;
        for (Annotation annotation : annotations) {
            ParameterHandler<?> annotationAction = parseParameterAnnotation(
                    p, parameterType, annotations, annotation);

            if (annotationAction == null) continue;

            if (result != null) {
                throw parameterError(method, p, "Multiple Retrofit annotations found, only one allowed.");
            }

            result = annotationAction;
        }

        if (result == null) {
            throw parameterError(method, p, "No Retrofit annotation found.");
        }

        return result;
    }

    private ParameterHandler<?> parseParameterAnnotation(
            int p, Type type, Annotation[] annotations, Annotation annotation) {
        if (annotation instanceof retrofit2.http.Path) {
            retrofit2.http.Path path = (retrofit

接着上面的继续分析

4.5 RequestFactory.parseAnnotations() 方法

4.5.1 parseParameterAnnotation 方法详细解析

java

private ParameterHandler<?> parseParameterAnnotation(
        int p, Type type, Annotation[] annotations, Annotation annotation) {
    if (annotation instanceof retrofit2.http.Path) {
        retrofit2.http.Path path = (retrofit2.http.Path) annotation;
        String name = path.value();
        validatePathName(p, name);
        // 创建 Path 类型的 ParameterHandler,用于处理路径参数
        return new ParameterHandler.Path<>(name,
                retrofit.stringConverter(type, annotations));
    } else if (annotation instanceof retrofit2.http.Query) {
        retrofit2.http.Query query = (retrofit2.http.Query) annotation;
        String name = query.value();
        // 创建 Query 类型的 ParameterHandler,用于处理查询参数
        return new ParameterHandler.Query<>(name,
                retrofit.stringConverter(type, annotations), query.encoded());
    } else if (annotation instanceof retrofit2.http.QueryMap) {
        if (!Map.class.isAssignableFrom(Utils.getRawType(type))) {
            throw parameterError(method, p, "@QueryMap parameter type must be Map.");
        }
        Type keyType = Utils.getSupertype(type, Map.class, String.class);
        if (keyType != String.class) {
            throw parameterError(method, p, "@QueryMap keys must be of type String.");
        }
        Type valueType = Utils.getSupertype(type, Map.class, Object.class);
        // 创建 QueryMap 类型的 ParameterHandler,用于处理查询参数映射
        return new ParameterHandler.QueryMap<>(
                retrofit.stringConverter(valueType, annotations),
                ((retrofit2.http.QueryMap) annotation).encoded());
    } else if (annotation instanceof retrofit2.http.Header) {
        retrofit2.http.Header header = (retrofit2.http.Header) annotation;
        String name = header.value();
        // 创建 Header 类型的 ParameterHandler,用于处理请求头参数
        return new ParameterHandler.Header<>(name,
                retrofit.stringConverter(type, annotations));
    } else if (annotation instanceof retrofit2.http.HeaderMap) {
        if (!Map.class.isAssignableFrom(Utils.getRawType(type))) {
            throw parameterError(method, p, "@HeaderMap parameter type must be Map.");
        }
        Type keyType = Utils.getSupertype(type, Map.class, String.class);
        if (keyType != String.class) {
            throw parameterError(method, p, "@HeaderMap keys must be of type String.");
        }
        Type valueType = Utils.getSupertype(type, Map.class, Object.class);
        // 创建 HeaderMap 类型的 ParameterHandler,用于处理请求头参数映射
        return new ParameterHandler.HeaderMap<>(
                retrofit.stringConverter(valueType, annotations));
    } else if (annotation instanceof retrofit2.http.Field) {
        if (!isFormEncoded) {
            throw parameterError(method, p, "@Field parameters can only be used with form encoding.");
        }
        retrofit2.http.Field field = (retrofit2.http.Field) annotation;
        String name = field.value();
        // 创建 Field 类型的 ParameterHandler,用于处理表单字段参数
        return new ParameterHandler.Field<>(name,
                retrofit.stringConverter(type, annotations), field.encoded());
    } else if (annotation instanceof retrofit2.http.FieldMap) {
        if (!isFormEncoded) {
            throw parameterError(method, p, "@FieldMap parameters can only be used with form encoding.");
        }
        if (!Map.class.isAssignableFrom(Utils.getRawType(type))) {
            throw parameterError(method, p, "@FieldMap parameter type must be Map.");
        }
        Type keyType = Utils.getSupertype(type, Map.class, String.class);
        if (keyType != String.class) {
            throw parameterError(method, p, "@FieldMap keys must be of type String.");
        }
        Type valueType = Utils.getSupertype(type, Map.class, Object.class);
        // 创建 FieldMap 类型的 ParameterHandler,用于处理表单字段参数映射
        return new ParameterHandler.FieldMap<>(
                retrofit.stringConverter(valueType, annotations),
                ((retrofit2.http.FieldMap) annotation).encoded());
    } else if (annotation instanceof retrofit2.http.Part) {
        if (!isMultipart) {
            throw parameterError(method, p, "@Part parameters can only be used with multipart encoding.");
        }
        retrofit2.http.Part part = (retrofit2.http.Part) annotation;
        String name = part.value();
        if (name.isEmpty()) {
            return new ParameterHandler.Part<>();
        }
        MediaType mediaType = null;
        if (!"*/*".equals(name)) {
            try {
                mediaType = MediaType.get(name);
            } catch (IllegalArgumentException e) {
                throw parameterError(method, p, "Malformed media type: %s", name);
            }
        }
        // 创建 Part 类型的 ParameterHandler,用于处理多部分请求的部分数据
        return new ParameterHandler.Part<>(name, mediaType,
                retrofit.stringConverter(type, annotations));
    } else if (annotation instanceof retrofit2.http.PartMap) {
        if (!isMultipart) {
            throw parameterError(method, p, "@PartMap parameters can only be used with multipart encoding.");
        }
        if (!Map.class.isAssignableFrom(Utils.getRawType(type))) {
            throw parameterError(method, p, "@PartMap parameter type must be Map.");
        }
        Type keyType = Utils.getSupertype(type, Map.class, String.class);
        if (keyType != String.class) {
            throw parameterError(method, p, "@PartMap keys must be of type String.");
        }
        Type valueType = Utils.getSupertype(type, Map.class, Object.class);
        // 创建 PartMap 类型的 ParameterHandler,用于处理多部分请求的部分数据映射
        return new ParameterHandler.PartMap<>(
                retrofit.stringConverter(valueType, annotations));
    } else if (annotation instanceof retrofit2.http.Body) {
        if (hasBody) {
            // 创建 Body 类型的 ParameterHandler,用于处理请求体
            return new ParameterHandler.Body<>(retrofit.requestBodyConverter(type, annotations, methodAnnotations));
        }
        throw parameterError(method, p, "@Body parameters cannot be used with HTTP methods "
                + "that do not have a request body (e.g., GET, HEAD).");
    } else if (annotation instanceof retrofit2.http.Tag) {
        // 创建 Tag 类型的 ParameterHandler,用于设置请求标签
        return new ParameterHandler.Tag<>(type);
    }

    return null;
}

这个方法会根据不同的注解类型创建不同的 ParameterHandler 对象,这些对象负责处理接口方法参数在请求中的不同使用方式,比如作为路径参数、查询参数、请求头参数等。

4.5.2 build 方法总结

java

RequestFactory build() {
    // 解析方法注解
    for (Annotation annotation : methodAnnotations) {
        parseMethodAnnotation(annotation);
    }

    if (httpMethod == null) {
        throw methodError(method, "HTTP method annotation is required (e.g., @GET, @POST, etc.).");
    }

    // 解析参数注解
    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(method, p, "Parameter type must not include a type variable or wildcard: %s",
                    parameterType);
        }

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

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

    if (relativeUrl == null && !hasBody) {
        throw methodError(method, "Non-body HTTP method cannot contain @Body.");
    }

    if (isFormEncoded && isMultipart) {
        throw methodError(method, "Only one encoding annotation is allowed.");
    }

    return new RequestFactory(this);
}

build 方法首先解析方法上的注解,确定 HTTP 请求方法、路径等信息。然后解析每个参数上的注解,创建对应的 ParameterHandler 数组。最后进行一些合法性检查,确保请求配置的正确性,最终创建并返回 RequestFactory 对象。

五、接口方法的调用

5.1 InvocationHandler.invoke() 方法回顾

java

@Override
public Object invoke(Object proxy, Method method, Object[] args)
        throws Throwable {
    // 如果调用的是 Object 类的方法,直接调用
    if (method.getDeclaringClass() == Object.class) {
        return method.invoke(this, args);
    }
    // 如果是默认方法,根据平台进行处理
    if (platform.isDefaultMethod(method)) {
        return platform.invokeDefaultMethod(method, service, proxy, args);
    }
    // 创建 ServiceMethod 对象
    ServiceMethod<Object, Object> serviceMethod =
            (ServiceMethod<Object, Object>) loadServiceMethod(method);
    // 创建 OkHttpCall 对象
    OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
    // 通过 CallAdapter 进行适配
    return serviceMethod.callAdapter.adapt(okHttpCall);
}

当调用接口方法时,会触发 InvocationHandlerinvoke 方法。该方法首先判断调用的是否为 Object 类的方法或者接口的默认方法,若是则直接处理。否则,会加载 ServiceMethod 对象,创建 OkHttpCall 对象,最后通过 CallAdapter 进行适配。

5.2 OkHttpCall

5.2.1 类的基本结构和成员变量

java

final class OkHttpCall<T> implements Call<T> {
    private final ServiceMethod<T, ?> serviceMethod;
    private final Object[] args;
    private volatile boolean canceled;

    private @Nullable okhttp3.Call rawCall;
    private @Nullable Throwable creationFailure;
    private boolean executed;

    OkHttpCall(ServiceMethod<T, ?> serviceMethod, Object[] args) {
        this.serviceMethod = serviceMethod;
        this.args = args;
    }
    // ...其他方法
}

OkHttpCall 类实现了 Call 接口,封装了 ServiceMethod 和方法参数。rawCall 是 OkHttp 的 Call 对象,用于实际执行 HTTP 请求。executed 标志该请求是否已经执行过,canceled 标志请求是否被取消。

5.2.2 request 方法

java

@Override
public synchronized Request request() {
    okhttp3.Call call = rawCall;
    if (call != null) {
        return call.request();
    }
    if (creationFailure != null) {
        if (creationFailure instanceof IOException) {
            throw new RuntimeException("Unable to create request.", creationFailure);
        } else {
            throw (RuntimeException) creationFailure;
        }
    }

    try {
        // 创建 OkHttp 的 Request 对象
        rawCall = call = serviceMethod.toCall(args);
        return call.request();
    } catch (RuntimeException | Error e) {
        creationFailure = e;
        throw e;
    }
}

request 方法用于获取实际的 OkHttp 请求对象。如果 rawCall 已经创建,则直接返回其请求对象。如果创建请求时出现异常,会抛出相应的异常。否则,调用 serviceMethod.toCall(args) 方法创建 rawCall 并返回其请求对象。

5.2.3 enqueue 方法

java

@Override
public void enqueue(final Callback<T> callback) {
    checkNotNull(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 {
                // 创建 OkHttp 的 Call 对象
                rawCall = call = serviceMethod.toCall(args);
            } catch (Throwable t) {
                failure = creationFailure = t;
            }
        }
    }

    if (failure != null) {
        // 处理创建请求时的异常
        callback.onFailure(this, failure);
        return;
    }

    if (canceled) {
        call.cancel();
    }

    // 执行请求并处理响应
    call.enqueue(new okhttp3.Callback() {
        @Override
        public void onFailure(okhttp3.Call call, IOException e) {
            // 切换到主线程回调失败结果
            callbackOnMain(e);
        }

        @Override
        public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {
            Response<T> response;
            try {
                // 解析响应结果
                response = parseResponse(rawResponse);
            } catch (Throwable e) {
                // 处理解析响应时的异常
                callbackOnMain(e);
                return;
            }

            // 切换到主线程回调成功结果
            callbackOnMain(response);
        }
    });
}

// 切换到主线程回调的辅助方法
private void callbackOnMain(final Throwable t) {
    // 获取主线程的执行器
    executorService.execute(new Runnable() {
        @Override
        public void run() {
            callback.onFailure(OkHttpCall.this, t);
        }
    });
}

private void callbackOnMain(final Response<T> response) {
    executorService.execute(new Runnable() {
        @Override
        public void run() {
            if (response.isSuccessful()) {
                callback.onResponse(OkHttpCall.this, response);
            } else {
                callback.onFailure(OkHttpCall.this, new IOException("HTTP " + response.code()));
            }
        }
    });
}

enqueue 方法用于异步执行请求。首先进行同步控制,确保请求只执行一次。然后创建 rawCall 对象,如果创建过程中出现异常,直接回调失败结果。接着判断请求是否被取消,若取消则取消 rawCall。最后使用 rawCallenqueue 方法异步执行请求,并在回调中处理响应结果。callbackOnMain 方法用于将回调切换到主线程。

5.2.4 parseResponse 方法

java

private Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
    ResponseBody rawBody = rawResponse.body();

    // 解析响应头
    Headers headers = Headers.of(rawResponse.headers());

    if (!rawResponse.isSuccessful()) {
        // 处理非成功响应
        rawBody.close();
        return Response.error(parseErrorBodyIfPossible(rawResponse), headers);
    }

    if (rawBody == null) {
        // 处理空响应体
        return Response.success(null, headers);
    }

    // 解析响应体
    T body = serviceMethod.toResponse(rawBody);
    return Response.success(body, headers);
}

// 解析错误响应体
private IOException parseErrorBodyIfPossible(okhttp3.Response rawResponse) {
    try {
        return serviceMethod.parseError(rawResponse);
    } catch (RuntimeException e) {
        return e;
    } catch (IOException e) {
        return e;
    } catch (Throwable t) {
        return new RuntimeException(t);
    }
}

parseResponse 方法用于解析 OkHttp 的响应结果。如果响应状态码不是 2xx,会处理错误响应。如果响应体为空,返回成功但 bodynull 的响应。否则,调用 serviceMethod.toResponse(rawBody) 方法解析响应体并返回成功响应。

5.3 ServiceMethod.toCall 方法

java

okhttp3.Call toCall(Object... args) {
    // 创建 OkHttp 的 Request 对象
    Request request = requestFactory.create(args);
    // 使用 OkHttp 的 Call.Factory 创建 Call 对象
    return callFactory.newCall(request);
}

toCall 方法调用 requestFactory.create(args) 方法创建 OkHttp 的 Request 对象,然后使用 callFactory 创建 Call 对象,用于实际执行 HTTP 请求。

5.4 RequestFactory.create 方法

java

Request create(Object... args) {
    // 解析请求 URL
    HttpUrl baseUrl = this.baseUrl;
    String relativeUrl = this.relativeUrl;
    HttpUrl.Builder urlBuilder = baseUrl.newBuilder(relativeUrl);
    if (urlBuilder == null) {
        throw new IllegalArgumentException("Malformed URL.");
    }

    // 解析请求参数
    ParameterHandler<?>[] parameterHandlers = this.parameterHandlers;
    Headers.Builder headersBuilder = new Headers.Builder();
    RequestBody body = null;
    for (int i = 0; i < parameterHandlers.length; i++) {
        parameterHandlers[i].apply(args[i], urlBuilder, headersBuilder, bodyBuilder);
    }

    // 创建 OkHttp 的 Request 对象
    return new Request.Builder()
           .url(urlBuilder.build())
           .headers(headersBuilder.build())
           .method(httpMethod, bodyBuilder.build())
           .build();
}

create 方法根据 baseUrlrelativeUrl 构建请求 URL。然后遍历 parameterHandlers 数组,将方法参数应用到请求的 URL、请求头和请求体中。最后使用 Request.Builder 创建 OkHttp 的 Request 对象。

六、CallAdapter 的适配过程

6.1 CallAdapter 接口和工厂类

java

public interface CallAdapter<R, T> {
    // 获取响应类型
    Type responseType();

    // 适配 Call 对象
    T adapt(Call<R> call);

    // 工厂类,用于创建 CallAdapter 对象
    abstract class Factory {
        // 根据返回类型和注解创建 CallAdapter 对象
        public abstract @Nullable CallAdapter<?, ?> get(Type returnType, Annotation[] annotations,
                                                        Retrofit retrofit);

        // 辅助方法,用于获取类型中的原始类型
        protected static Type getParameterUpperBound(int index, ParameterizedType type) {
            return Utils.getParameterUpperBound(index, type);
        }

        // 辅助方法,用于获取类型中的原始类型
        protected static Class<?> getRawType(Type type) {
            return Utils.getRawType(type);
        }
    }
}

CallAdapter 接口定义了两个方法,responseType 用于获取响应类型,adapt 用于适配 Call 对象。Factory 是一个抽象类,用于创建 CallAdapter 对象。

6.2 ExecutorCallAdapterFactoryExecutorCallAdapter

java

public final class ExecutorCallAdapterFactory extends CallAdapter.Factory {
    final Executor callbackExecutor;

    public ExecutorCallAdapterFactory(Executor callbackExecutor) {
        this.callbackExecutor = callbackExecutor;
    }

    @Override
    public @Nullable CallAdapter<?, ?> get(Type returnType, Annotation[] annotations,
                                           Retrofit retrofit) {
        if (getRawType(returnType) != Call.class) {
            return null;
        }
        final Type responseType = Utils.getCallResponseType(returnType);
        return new ExecutorCallAdapter<>(callbackExecutor, responseType);
    }
}

final class ExecutorCallAdapter<T, R> implements CallAdapter<T, R> {
    private final Executor callbackExecutor;
    private final Type responseType;

    ExecutorCallAdapter(Executor callbackExecutor, Type responseType) {
        this.callbackExecutor = callbackExecutor;
        this.responseType = responseType;
    }

    @Override
    public Type responseType() {
        return responseType;
    }

    @Override
    public R adapt(Call<T> call) {
        // 创建适配后的 Call 对象
        return (R) new ExecutorCallbackCall<>(callbackExecutor, call);
    }
}

final class ExecutorCallbackCall<T> implements Call<T> {
    private final Executor callbackExecutor;
    private final Call<T> delegate;

    ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
        this.callbackExecutor = callbackExecutor;
        this.delegate = delegate;
    }

    @Override
    public void enqueue(final Callback<T> callback) {
        // 检查回调是否为 null
        checkNotNull(callback, "callback == null");

        // 执行原始请求,并在回调时切换线程
        delegate.enqueue(new Callback<T>() {
            @Override
            public void onResponse(Call<T> call, final Response<T> response) {
                // 切换到指定线程回调
                callbackExecutor.execute(new Runnable() {
                    @Override
                    public void run() {
                        if (delegate.isCanceled()) {
                            callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled"));
                        } else {
                            callback.onResponse(ExecutorCallbackCall.this, response);
                        }
                    }
                });
            }

            @Override
            public void onFailure(Call<T> call, final Throwable t) {
                // 切换到指定线程回调
                callbackExecutor.execute(new Runnable() {
                    @Override
                    public void run() {
                        callback.onFailure(ExecutorCallbackCall.this, t);
                    }
                });
            }
        });
    }

    // 其他方法直接委托给原始 Call 对象
    @Override
    public Response<T> execute() throws IOException {
        return delegate.execute();
    }

    @Override
    public boolean isExecuted() {
        return delegate.isExecuted();
    }

    @Override
    public void cancel() {
        delegate.cancel();
    }

    @Override
    public boolean isCanceled() {
        return delegate.isCanceled();
    }

    @Override
    public Call<T> clone() {
        return new ExecutorCallbackCall<>(callbackExecutor, delegate.clone());
    }

    @Override
    public Request request() {
        return delegate.request();
    }
}

ExecutorCallAdapterFactory 是默认的 CallAdapter 工厂类,它会根据返回类型判断是否为 Call 类型,如果是则创建 ExecutorCallAdapter 对象。ExecutorCallAdapteradapt 方法会创建 ExecutorCallbackCall 对象,该对象会将回调切换到指定的线程。

七、Converter 的转换过程

7.1 Converter 接口和工厂类

java

public interface Converter<F, T> {
    // 转换方法
    T convert(F value) throws IOException;

    // 工厂类,用于创建 Converter 对象
    abstract class Factory {
        // 创建请求体转换器
        public @Nullable Converter<?, RequestBody> requestBodyConverter(Type type,
                                                                        Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
            return null;
        }

        // 创建响应体转换器
        public @Nullable Converter<ResponseBody, ?> responseBodyConverter(Type type,
                                                                           Annotation[] annotations, Retrofit retrofit) {
            return null;
        }

        // 创建字符串转换器
        public @Nullable Converter<?, String> stringConverter(Type type, Annotation[] annotations,
                                                              Retrofit retrofit) {
            return null;
        }
    }
}

Converter 接口定义了 convert 方法,用于进行数据转换。Factory 是一个抽象类,提供了创建请求体转换器、响应体转换器和字符串转换器的方法。

7.2 GsonConverterFactory 和相关转换器

java

public final class GsonConverterFactory extends Converter.Factory {
    private final Gson gson;

    private GsonConverterFactory(Gson gson) {
        this.gson = gson;
    }

    public static GsonConverterFactory create() {
        return create(new Gson());
    }

    public static GsonConverterFactory create(Gson gson) {
        return new GsonConverterFactory(gson);
    }

    @Override
    public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
        return new GsonResponseBodyConverter<>(gson, type);
    }

    @Override
    public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
        return new GsonRequestBodyConverter<>(gson, type);
    }
}

final class GsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
    private final Gson gson;
    private final TypeAdapter<T> adapter;

    GsonResponseBodyConverter(Gson gson, Type type) {
        this.gson = gson;
        this.adapter = gson.getAdapter(TypeToken.get(type));
    }

    @Override
    public T convert(ResponseBody value) throws IOException {
        JsonReader jsonReader = gson.newJsonReader(value.charStream());
        try {
            return adapter.read(jsonReader);
        } finally {
            value.close();
        }
    }
}

final class GsonRequestBodyConverter<T> implements Converter<T, RequestBody> {
    private static final MediaType MEDIA_TYPE = MediaType.get("application/json; charset=UTF-8");
    private static final Charset UTF_8 = Charset.forName("UTF-8");

    private final Gson gson;
    private final TypeAdapter<T> adapter;

    GsonRequestBodyConverter(Gson gson, Type type) {
        this.gson = gson;
        this.adapter = gson.getAdapter(TypeToken.get(type));
    }

    @Override
    public RequestBody convert(T value) throws IOException {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        JsonWriter jsonWriter = gson.newJsonWriter(new OutputStreamWriter(out, UTF_8));
        adapter.write(jsonWriter, value);
        jsonWriter.close();
        return RequestBody.create(MEDIA_TYPE, out.toByteArray());
    }
}

GsonConverterFactory 是一个使用 Gson 进行序列化和反序列化的 Converter 工厂类。它会创建 GsonResponseBodyConverterGsonRequestBodyConverter,分别用于将响应体和请求参数转换为指定类型。

八、总结

通过对 Retrofit 接口代理与调用模块的源码分析,我们可以看到 Retrofit 是一个设计精巧、模块化程度高的框架。其核心流程如下:

8.1 核心流程概述

  • Retrofit 实例创建:利用 Retrofit.Builder 类对 Retrofit 实例的各项配置进行设置,像请求工厂、基础 URL、调用适配器工厂、转换器工厂以及回调执行器等。最终调用 build() 方法生成 Retrofit 实例。
  • 接口代理对象创建:借助 Retrofit 实例的 create() 方法,运用 Java 动态代理机制创建 API 接口的代理对象。在 InvocationHandlerinvoke() 方法里处理接口方法的调用,涵盖加载 ServiceMethod 对象、创建 OkHttpCall 对象以及通过 CallAdapter 进行适配等操作。
  • 方法注解解析ServiceMethod.parseAnnotations() 方法对 API 接口方法的注解加以解析,创建 RequestFactoryCallAdapterConverter 对象,并最终构建 ServiceMethod 对象。RequestFactory 负责解析请求相关注解,明确 HTTP 请求方法、路径以及参数处理方式。
  • 请求执行OkHttpCall 类封装了 ServiceMethod 和方法参数,其 enqueue() 方法用于异步执行请求。在该方法中,会创建 OkHttp 的 Call 对象,若创建过程出现异常则回调失败结果,接着判断请求是否取消,若未取消则使用 Call 对象的 enqueue() 方法异步执行请求,并处理响应结果。
  • 结果适配与转换CallAdapter 负责将网络请求结果适配为不同类型,例如 CallObservable 等。Converter 负责对请求参数和响应结果进行序列化和反序列化,Retrofit 提供了多种默认的 Converter,像 GsonConverterFactoryMoshiConverterFactory 等。

8.2 设计优点

  • 高度模块化:Retrofit 将不同功能拆分成多个模块,如 CallAdapterConverter 等,每个模块职责明确。开发者能够根据自身需求替换或扩展这些模块,例如使用不同的 CallAdapter 来适配 RxJava、Kotlin Coroutines 等异步编程库,或者使用不同的 Converter 来处理不同格式的数据。
  • 注解驱动:通过注解来定义 API 接口方法的请求信息,如 HTTP 请求方法、路径、参数等,使代码简洁且易于理解和维护。同时,注解的使用也提高了代码的可读性和可维护性,开发者可以清晰地看到每个方法的请求信息。
  • 与 OkHttp 集成:Retrofit 底层使用 OkHttp 作为 HTTP 客户端,借助 OkHttp 的强大功能,如连接池管理、拦截器、缓存等,提高了网络请求的性能和稳定性。

8.3 性能优化点

  • 缓存机制:可利用 OkHttp 的缓存功能,减少不必要的网络请求。通过设置合适的缓存策略,如根据响应头的 Cache-Control 字段进行缓存,能够提高应用的响应速度和节省用户流量。
  • 拦截器使用:使用 OkHttp 的拦截器对请求和响应进行拦截处理,例如添加请求头、记录日志、重试请求等。合理使用拦截器可以提高代码的复用性和可维护性。
  • 异步处理:Retrofit 支持异步请求,使用 enqueue() 方法进行异步调用,避免在主线程中进行网络请求,防止阻塞主线程,提高应用的响应性能。

8.4 可扩展性分析

  • 自定义 CallAdapter:开发者可以自定义 CallAdapter 来适配不同的异步编程库,如 RxJava、Kotlin Coroutines 等。通过实现 CallAdapter.Factory 接口和 CallAdapter 接口,开发者可以将网络请求结果转换为自定义的类型,实现更灵活的异步处理。
  • 自定义 Converter:可以自定义 Converter 来处理不同格式的数据,如 XML、Protocol Buffers 等。通过实现 Converter.Factory 接口和 Converter 接口,开发者可以将请求参数和响应结果转换为自定义的格式,满足不同的业务需求。

8.5 潜在问题与解决方案

  • 注解使用不当:若注解使用错误,可能会导致请求配置错误。开发者需要仔细阅读 Retrofit 的文档,正确使用各种注解,同时在开发过程中进行充分的测试,确保请求配置的正确性。
  • 内存泄漏风险:在使用异步请求时,如果没有正确处理回调,可能会导致内存泄漏。开发者需要在适当的时候取消请求,避免在 Activity 或 Fragment 销毁时仍然持有引用。可以在 onDestroy() 方法中调用 call.cancel() 方法取消请求。
  • 异常处理复杂:网络请求过程中可能会出现各种异常,如网络连接失败、服务器错误等。开发者需要在代码中进行全面的异常处理,确保应用在出现异常时能够给出友好的提示信息。可以在 CallbackonFailure() 方法中对不同的异常进行处理,根据异常类型给出不同的提示信息。

九、拓展与未来发展趋势

9.1 与新兴技术的融合

  • Kotlin 协程:随着 Kotlin 在 Android 开发中的广泛应用,Retrofit 可以更好地与 Kotlin 协程集成。通过自定义 CallAdapter,可以将网络请求封装为协程的挂起函数,使异步编程更加简洁和直观。例如,可以创建一个 CoroutineCallAdapterFactory,将 Call 对象转换为 Deferred 或直接在协程中使用的挂起函数。
  • Flow:Kotlin 的 Flow 是一种异步数据流,它可以用于处理多个连续的异步事件。Retrofit 可以与 Flow 集成,将网络请求的响应转换为 Flow 流,方便开发者进行数据的流式处理和组合。例如,可以通过自定义 CallAdapterCall 对象转换为 Flow 对象,实现数据的实时更新和处理。

9.2 性能优化的进一步探索

  • HTTP/3 支持:HTTP/3 是 HTTP 协议的下一代版本,它基于 QUIC 协议,具有更快的连接速度和更好的性能。Retrofit 可以考虑支持 HTTP/3,以进一步提高网络请求的性能。这需要对 OkHttp 进行升级,使其支持 HTTP/3 协议,并在 Retrofit 中进行相应的配置和适配。
  • 智能缓存策略:结合机器学习和数据分析技术,实现智能缓存策略。根据用户的使用习惯、网络环境等因素,动态调整缓存的有效期和缓存策略,提高缓存的命中率和性能。例如,可以分析用户的请求频率和请求内容,预测用户可能的请求,提前进行缓存。

9.3 安全与隐私保护

  • 数据加密:在网络请求过程中,对敏感数据进行加密处理,确保数据的安全性。可以在请求体和响应体中添加加密算法,对数据进行加密和解密操作。例如,使用 AES 加密算法对请求参数和响应结果进行加密,防止数据在传输过程中被窃取。
  • 隐私保护:遵守相关的隐私法规,如 GDPR 等,对用户的个人信息进行保护。在网络请求中,避免传输不必要的个人信息,对必须传输的个人信息进行脱敏处理。例如,对用户的手机号码、身份证号码等敏感信息进行脱敏处理,只传输部分信息。

9.4 跨平台支持

  • Flutter:随着 Flutter 在跨平台开发中的流行,Retrofit 可以考虑提供对 Flutter 的支持。可以开发一个 Flutter 版本的 Retrofit 库,让 Flutter 开发者也能够享受到 Retrofit 的便捷性和高性能。这需要将 Retrofit 的核心功能进行重构,使其能够在 Flutter 环境中运行。

  • React Native:同样,Retrofit 也可以考虑支持 React Native 平台。通过开发一个 React Native 版本的 Retrofit 库,为 React Native 开发者提供一个强大的网络请求解决方案。这需要与 React Native 的生态系统进行集成,实现与 JavaScript 代码的交互。

综上所述,Retrofit 作为一个优秀的网络请求框架,在 Android 开发中发挥着重要作用。通过深入分析其源码,我们不仅可以了解其内部实现原理,还可以发现其潜在的优化点和拓展方向。随着技术的不断发展,Retrofit 有望在性能、功能和跨平台支持等方面取得更大的进步。


网站公告

今日签到

点亮在社区的每一天
去签到