当前位置: 首页 > news >正文

站内推广方式有哪些比较好的公关公司

站内推广方式有哪些,比较好的公关公司,百度seo关键词怎么设置,展示型网站一样做seo优化吗一、引言 在现代 Android 和 Java 开发中#xff0c;网络请求是不可或缺的一部分。Retrofit 作为 Square 公司开源的一款强大的类型安全的 HTTP 客户端#xff0c;凭借其简洁易用的 API 和高效的性能#xff0c;在开发者社区中广受欢迎。Retrofit 的核心特性之一便是通过注…一、引言 在现代 Android 和 Java 开发中网络请求是不可或缺的一部分。Retrofit 作为 Square 公司开源的一款强大的类型安全的 HTTP 客户端凭借其简洁易用的 API 和高效的性能在开发者社区中广受欢迎。Retrofit 的核心特性之一便是通过注解来定义 HTTP 请求这种方式使得代码更加清晰、易读且易于维护。本文将深入 Retrofit 框架的源码对其注解定义与解析模块进行全面且细致的分析揭示其背后的实现原理。 二、Retrofit 框架概述 2.1 Retrofit 的基本工作流程 Retrofit 的主要工作流程可以概括为以下几个步骤 定义服务接口开发者使用注解定义一个接口该接口包含了各种 HTTP 请求方法。创建 Retrofit 实例通过 Retrofit.Builder 构建 Retrofit 实例配置请求的基础 URL、转换器工厂、调用适配器工厂等。创建服务代理对象使用 Retrofit 实例创建服务接口的代理对象。发起请求调用服务代理对象的方法发起 HTTP 请求并处理响应结果。 2.2 注解在 Retrofit 中的作用 注解在 Retrofit 中扮演着至关重要的角色它们用于描述 HTTP 请求的各个方面包括请求方法如 GET、POST 等、请求路径、请求参数、请求头、请求体等。通过注解开发者可以以一种声明式的方式定义请求而无需编写繁琐的网络请求代码。 三、Retrofit 注解的定义 3.1 HTTP 请求方法注解 3.1.1 GET 注解 java import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;/*** 表示 HTTP GET 请求的注解*/ Documented // 该注解只能应用于方法上 Target(ElementType.METHOD) // 该注解在运行时保留以便通过反射获取 Retention(RetentionPolicy.RUNTIME) public interface GET {/*** 指定请求的相对路径* return 请求的相对路径默认为空字符串*/String value() default ; }GET 注解用于标记一个方法为 HTTP GET 请求value 属性用于指定请求的相对路径。例如 java public interface ApiService {GET(users/{id})CallUser getUser(Path(id) int userId); }3.1.2 其他 HTTP 请求方法注解 除了 GET 注解Retrofit 还提供了 POST、PUT、DELETE、HEAD、OPTIONS 和 PATCH 等注解它们的定义方式与 GET 注解类似只是用于不同的 HTTP 请求方法。 3.2 请求路径与参数注解 3.2.1 Path 注解 java import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;/*** 用于替换 URL 中占位符的注解*/ Documented // 该注解只能应用于方法的参数上 Target(ElementType.PARAMETER) // 该注解在运行时保留 Retention(RetentionPolicy.RUNTIME) public interface Path {/*** 指定 URL 中的占位符名称* return 占位符名称*/String value();/*** 指定是否对参数进行 URL 编码默认为 false* return 是否进行 URL 编码*/boolean encoded() default false; }Path 注解用于替换 URL 中的占位符例如在上面的 getUser 方法中Path(id) 表示将 userId 参数的值替换到 URL 中的 {id} 占位符处。 3.2.2 Query 和 QueryMap 注解 java import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;/*** 用于添加查询参数到 URL 中的注解*/ Documented // 该注解只能应用于方法的参数上 Target(ElementType.PARAMETER) // 该注解在运行时保留 Retention(RetentionPolicy.RUNTIME) public interface Query {/*** 指定查询参数的名称* return 查询参数的名称*/String value();/*** 指定是否对参数进行 URL 编码默认为 false* return 是否进行 URL 编码*/boolean encoded() default false; }import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;/*** 用于添加多个查询参数到 URL 中的注解*/ Documented // 该注解只能应用于方法的参数上 Target(ElementType.PARAMETER) // 该注解在运行时保留 Retention(RetentionPolicy.RUNTIME) public interface QueryMap {/*** 指定是否对参数进行 URL 编码默认为 false* return 是否进行 URL 编码*/boolean encoded() default false; }Query 注解用于添加单个查询参数到 URL 中QueryMap 注解用于添加多个查询参数。例如 java public interface ApiService {GET(search)CallListItem search(Query(keyword) String keyword, Query(page) int page);GET(search)CallListItem searchWithMap(QueryMap MapString, String queryParams); }3.2.3 Header 和 HeaderMap 注解 java import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;/*** 用于添加请求头的注解*/ Documented // 该注解只能应用于方法的参数上 Target(ElementType.PARAMETER) // 该注解在运行时保留 Retention(RetentionPolicy.RUNTIME) public interface Header {/*** 指定请求头的名称* return 请求头的名称*/String value(); }import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;/*** 用于添加多个请求头的注解*/ Documented // 该注解只能应用于方法的参数上 Target(ElementType.PARAMETER) // 该注解在运行时保留 Retention(RetentionPolicy.RUNTIME) public interface HeaderMap { }Header 注解用于添加单个请求头HeaderMap 注解用于添加多个请求头。例如 java public interface ApiService {GET(data)CallData getData(Header(Authorization) String token);GET(data)CallData getDataWithMap(HeaderMap MapString, String headers); }3.2.4 Body 注解 java import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;/*** 用于指定请求体的注解*/ Documented // 该注解只能应用于方法的参数上 Target(ElementType.PARAMETER) // 该注解在运行时保留 Retention(RetentionPolicy.RUNTIME) public interface Body { }Body 注解用于指定请求体通常用于 POST、PUT 等请求。例如 java public interface ApiService {POST(users)CallUser createUser(Body User user); }3.2.5 FormUrlEncoded、Field 和 FieldMap 注解 java import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;/*** 用于标记表单编码请求的注解*/ Documented // 该注解只能应用于方法上 Target(ElementType.METHOD) // 该注解在运行时保留 Retention(RetentionPolicy.RUNTIME) public interface FormUrlEncoded { }import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;/*** 用于添加表单字段的注解*/ Documented // 该注解只能应用于方法的参数上 Target(ElementType.PARAMETER) // 该注解在运行时保留 Retention(RetentionPolicy.RUNTIME) public interface Field {/*** 指定表单字段的名称* return 表单字段的名称*/String value();/*** 指定是否对参数进行 URL 编码默认为 false* return 是否进行 URL 编码*/boolean encoded() default false; }import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;/*** 用于添加多个表单字段的注解*/ Documented // 该注解只能应用于方法的参数上 Target(ElementType.PARAMETER) // 该注解在运行时保留 Retention(RetentionPolicy.RUNTIME) public interface FieldMap {/*** 指定是否对参数进行 URL 编码默认为 false* return 是否进行 URL 编码*/boolean encoded() default false; }FormUrlEncoded 注解用于标记一个方法为表单编码请求Field 注解用于添加单个表单字段FieldMap 注解用于添加多个表单字段。例如 java public interface ApiService {FormUrlEncodedPOST(login)CallLoginResponse login(Field(username) String username, Field(password) String password);FormUrlEncodedPOST(login)CallLoginResponse loginWithMap(FieldMap MapString, String fields); }3.2.6 Multipart、Part 和 PartMap 注解 java import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;/*** 用于标记多部分请求的注解*/ Documented // 该注解只能应用于方法上 Target(ElementType.METHOD) // 该注解在运行时保留 Retention(RetentionPolicy.RUNTIME) public interface Multipart { }import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;/*** 用于添加多部分请求中的一个部分的注解*/ Documented // 该注解只能应用于方法的参数上 Target(ElementType.PARAMETER) // 该注解在运行时保留 Retention(RetentionPolicy.RUNTIME) public interface Part {/*** 指定部分的名称* return 部分的名称*/String value() default ; }import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;/*** 用于添加多部分请求中的多个部分的注解*/ Documented // 该注解只能应用于方法的参数上 Target(ElementType.PARAMETER) // 该注解在运行时保留 Retention(RetentionPolicy.RUNTIME) public interface PartMap { }Multipart 注解用于标记一个方法为多部分请求Part 注解用于添加多部分请求中的一个部分PartMap 注解用于添加多部分请求中的多个部分。多部分请求常用于文件上传等场景。例如 java public interface ApiService {MultipartPOST(upload)CallUploadResponse uploadFile(Part(file; filenameimage.jpg) RequestBody file);MultipartPOST(upload)CallUploadResponse uploadFiles(PartMap MapString, RequestBody files); }3.3 其他注解 3.3.1 Headers 注解 java import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;/*** 用于添加多个请求头的注解*/ Documented // 该注解只能应用于方法上 Target(ElementType.METHOD) // 该注解在运行时保留 Retention(RetentionPolicy.RUNTIME) public interface Headers {/*** 指定请求头的数组* return 请求头的数组*/String[] value(); }Headers 注解用于在方法上添加多个请求头。例如 java public interface ApiService {Headers({Content-Type: application/json,Authorization: Bearer token123})GET(data)CallData getData(); }四、Retrofit 注解的解析 4.1 解析入口ServiceMethod 类 ServiceMethod 是 Retrofit 中解析注解的核心类它负责将接口方法上的注解信息解析为实际的 HTTP 请求信息。以下是 ServiceMethod 类的部分源码 java abstract class ServiceMethodT {/*** 解析接口方法上的注解创建 ServiceMethod 实例* param retrofit Retrofit 实例* param method 接口方法* param T 响应类型* return ServiceMethod 实例*/static T ServiceMethodT parseAnnotations(Retrofit retrofit, Method method) {// 创建 RequestFactory.Builder 实例用于构建 RequestFactoryRequestFactory.Builder requestFactoryBuilder new RequestFactory.Builder(retrofit, method);// 解析请求方法和路径相关的注解requestFactoryBuilder.parseMethodAnnotation(method.getAnnotations());// 获取方法的参数类型Type[] parameterTypes method.getGenericParameterTypes();// 获取方法的参数注解Annotation[][] parameterAnnotationsArray method.getParameterAnnotations();// 遍历方法的每个参数for (int p 0; p parameterTypes.length; p) {// 解析参数的注解requestFactoryBuilder.parseParameter(p, parameterTypes[p], parameterAnnotationsArray[p]);}// 构建 RequestFactory 实例RequestFactory requestFactory requestFactoryBuilder.build();// 获取方法的返回类型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 实例用于将 Call 对象转换为其他类型CallAdapterT, ? callAdapter createCallAdapter(retrofit, method, returnType, requestFactory);// 获取响应类型Type responseType callAdapter.responseType();if (Utils.hasUnresolvableType(responseType)) {throw methodError(method, Call return type must not include a type variable or wildcard: %s, returnType);}// 创建 Converter 实例用于将响应数据转换为指定类型ConverterResponseBody, T responseConverter createResponseConverter(retrofit, method, responseType);// 获取 OkHttpClient 实例okhttp3.Call.Factory callFactory retrofit.callFactory();// 创建 ServiceMethod 实例return new HttpServiceMethod(callFactory, requestFactory, callAdapter, responseConverter);}/*** 创建 CallAdapter 实例* param retrofit Retrofit 实例* param method 接口方法* param returnType 方法的返回类型* param requestFactory 请求工厂* param T 响应类型* return CallAdapter 实例*/private static T CallAdapterT, ? createCallAdapter(Retrofit retrofit, Method method, Type returnType, RequestFactory requestFactory) {try {// 通过 Retrofit 实例获取 CallAdapter.Factory 列表并调用其 get 方法创建 CallAdapter 实例return (CallAdapterT, ?) retrofit.callAdapter(returnType, method.getAnnotations());} catch (RuntimeException e) {throw methodError(method, e, Unable to create call adapter for %s, returnType);}}/*** 创建响应转换器实例* param retrofit Retrofit 实例* param method 接口方法* param responseType 响应类型* param T 响应类型* return 响应转换器实例*/private static T ConverterResponseBody, T createResponseConverter(Retrofit retrofit, Method method, Type responseType) {try {// 通过 Retrofit 实例获取 Converter.Factory 列表并调用其 responseBodyConverter 方法创建响应转换器实例return retrofit.responseBodyConverter(responseType, method.getAnnotations());} catch (RuntimeException e) {throw methodError(method, e, Unable to create converter for %s, responseType);}}/*** 抽象方法用于执行请求* param args 方法参数* return 响应结果*/abstract Nullable T invoke(Object[] args); }parseAnnotations 方法是解析的入口它接收 Retrofit 实例和 Method 实例作为参数通过以下步骤完成注解解析 创建 RequestFactory.Builder 实例用于构建 RequestFactory。调用 requestFactoryBuilder.parseMethodAnnotation 方法解析请求方法和路径相关的注解。遍历方法的每个参数调用 requestFactoryBuilder.parseParameter 方法解析参数的注解。构建 RequestFactory 实例。获取方法的返回类型并创建 CallAdapter 实例用于将 Call 对象转换为其他类型。获取响应类型并创建 Converter 实例用于将响应数据转换为指定类型。获取 OkHttpClient 实例并创建 ServiceMethod 实例。 4.2 解析请求方法和路径注解RequestFactory.Builder.parseMethodAnnotation 方法 java static final class Builder {// 存储请求方法如 GET、POST 等private String httpMethod;// 存储请求是否需要请求体private boolean hasBody;// 存储请求的相对路径private String relativeUrl;// 存储请求的请求头private okhttp3.Headers headers;// 存储路径中的占位符名称private ListString relativeUrlParamNames;// 标记是否为多部分请求private boolean isMultipart;// 标记是否为表单编码请求private boolean isFormEncoded;/*** 解析请求方法和路径相关的注解* param annotations 方法上的注解数组*/void parseMethodAnnotation(Annotation[] annotations) {for (Annotation annotation : annotations) {if (annotation instanceof HttpMethod) {// 如果注解是 HttpMethod 类型如 GET、POST 等HttpMethod httpMethodAnnotation (HttpMethod) annotation;// 获取请求方法this.httpMethod httpMethodAnnotation.value();// 判断是否需要请求体this.hasBody httpMethodAnnotation.hasBody();String path httpMethodAnnotation.path();if (!path.isEmpty()) {// 检查路径是否以 / 开头if (path.startsWith(/)) {throw methodError(method, %s path must not start with /: %s,httpMethodAnnotation.annotationType().getSimpleName(), path);}this.relativeUrl path;// 解析路径中的占位符this.relativeUrlParamNames parsePathParameters(path);}} else if (annotation instanceof Headers) {// 如果注解是 Headers 类型String[] headersToParse ((Headers) annotation).value();if (headersToParse.length 0) {throw methodError(method, Headers annotation is empty.);}// 解析请求头this.headers parseHeaders(headersToParse);} else if (annotation instanceof Multipart) {// 如果注解是 Multipart 类型if (this.hasBody) {throw methodError(method, Only one encoding annotation is allowed.);}this.isMultipart true;this.hasBody true;} else if (annotation instanceof FormUrlEncoded) {// 如果注解是 FormUrlEncoded 类型if (this.hasBody) {throw methodError(method, Only one encoding annotation is allowed.);}this.isFormEncoded true;this.hasBody true;}}if (httpMethod null) {throw methodError(method, HTTP method annotation is required (e.g., GET, POST, etc.).);}}/*** 解析路径中的占位符* param path 请求路径* return 占位符名称列表*/private static ListString parsePathParameters(String path) {// 定义正则表达式用于匹配路径中的占位符Matcher m PARAM_URL_REGEX.matcher(path);ListString patterns new ArrayList();while (m.find()) {String name m.group(1);if (name null) {continue;}if (patterns.contains(name)) {throw new IllegalArgumentException(URL path path has duplicate param name .);}patterns.add(name);}return patterns;}/*** 解析请求头* param headers 请求头数组* return OkHttp 的 Headers 实例*/private static okhttp3.Headers parseHeaders(String[] headers) {okhttp3.Headers.Builder builder new okhttp3.Headers.Builder();for (String header : headers) {int colon header.indexOf(:);if (colon -1 || colon 0 || colon header.length() - 1) {throw new IllegalArgumentException(Headers value must be in the form Name: Value. Found: header );}String name header.substring(0, colon).trim();String value header.substring(colon 1).trim();builder.add(name, value);}return builder.build();} }parseMethodAnnotation 方法遍历方法上的所有注解根据注解的类型进行不同的处理 如果注解是 HttpMethod 类型如 GET、POST 等获取请求方法、判断是否需要请求体并解析路径中的占位符。如果注解是 Headers 类型解析请求头。如果注解是 Multipart 类型标记为多部分请求。如果注解是 FormUrlEncoded 类型标记为表单编码请求。 4.3 解析参数注解RequestFactory.Builder.parseParameter 方法 java static final class Builder {// 存储参数处理器数组private ParameterHandler?[] parameterHandlers;/*** 解析方法参数的注解* param p 参数索引* param parameterType 参数类型* param annotations 参数上的注解数组*/void parseParameter(int p, Type parameterType, Nullable Annotation[] annotations) {if (annotations null) {throw parameterError(method, p, No Retrofit annotation found.);}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.);}// 将参数处理器添加到参数处理器数组中parameterHandlers[p] result;}/*** 解析单个参数注解* param p 参数索引* param type 参数类型* param annotations 参数上的注解数组* param annotation 当前要解析的注解* return 参数处理器*/private Nullable ParameterHandler? parseParameterAnnotation(int p, Type type, Annotation[] annotations, Annotation annotation) {if (annotation instanceof Path) {// 如果注解4.3 解析参数注解RequestFactory.Builder.parseParameter 方法续 java static final class Builder {// 存储参数处理器数组private ParameterHandler?[] parameterHandlers;/*** 解析方法参数的注解* param p 参数索引* param parameterType 参数类型* param annotations 参数上的注解数组*/void parseParameter(int p, Type parameterType, Nullable Annotation[] annotations) {if (annotations null) {throw parameterError(method, p, No Retrofit annotation found.);}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.);}// 将参数处理器添加到参数处理器数组中parameterHandlers[p] result;}/*** 解析单个参数注解* param p 参数索引* param type 参数类型* param annotations 参数上的注解数组* param annotation 当前要解析的注解* return 参数处理器*/private Nullable ParameterHandler? parseParameterAnnotation(int p, Type type, Annotation[] annotations, Annotation annotation) {if (annotation instanceof Path) {// 如果注解是 Path 类型Path path (Path) annotation;// 检查路径中是否包含该占位符if (!relativeUrlParamNames.contains(path.value())) {throw parameterError(method, p, Path parameter path.value() not found in relative URL relativeUrl );}// 检查参数类型是否为基本类型或字符串if (Utils.hasUnresolvableType(type)) {throw parameterError(method, p,Path parameter type must not include a type variable or wildcard: %s, type);}// 创建 PathParameterHandler 实例return new ParameterHandler.Path(path.value(), path.encoded(),converterFactory.stringConverter(type, annotations, retrofit));} else if (annotation instanceof Query) {// 如果注解是 Query 类型Query query (Query) annotation;// 检查参数类型是否为基本类型或字符串if (Utils.hasUnresolvableType(type)) {throw parameterError(method, p,Query parameter type must not include a type variable or wildcard: %s, type);}// 创建 QueryParameterHandler 实例return new ParameterHandler.Query(query.value(), query.encoded(),converterFactory.stringConverter(type, annotations, retrofit));} else if (annotation instanceof QueryMap) {// 如果注解是 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: %s, type);}Type valueType Utils.getSupertype(type, Map.class, Object.class);// 创建 QueryMapParameterHandler 实例return new ParameterHandler.QueryMap(converterFactory.stringConverter(valueType, annotations, retrofit));} else if (annotation instanceof Header) {// 如果注解是 Header 类型Header header (Header) annotation;// 检查参数类型是否为基本类型或字符串if (Utils.hasUnresolvableType(type)) {throw parameterError(method, p,Header parameter type must not include a type variable or wildcard: %s, type);}// 创建 HeaderParameterHandler 实例return new ParameterHandler.Header(header.value(),converterFactory.stringConverter(type, annotations, retrofit));} else if (annotation instanceof HeaderMap) {// 如果注解是 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: %s, type);}Type valueType Utils.getSupertype(type, Map.class, Object.class);// 创建 HeaderMapParameterHandler 实例return new ParameterHandler.HeaderMap(converterFactory.stringConverter(valueType, annotations, retrofit));} else if (annotation instanceof Body) {// 如果注解是 Body 类型if (isFormEncoded || isMultipart) {throw parameterError(method, p,Body parameters cannot be used with form or multi - part encoding.);}// 创建 BodyParameterHandler 实例return new ParameterHandler.Body(converterFactory.requestBodyConverter(type, annotations, methodAnnotations, retrofit));} else if (annotation instanceof Field) {// 如果注解是 Field 类型if (!isFormEncoded) {throw parameterError(method, p, Field parameters can only be used with form encoding.);}Field field (Field) annotation;// 检查参数类型是否为基本类型或字符串if (Utils.hasUnresolvableType(type)) {throw parameterError(method, p,Field parameter type must not include a type variable or wildcard: %s, type);}// 创建 FieldParameterHandler 实例return new ParameterHandler.Field(field.value(), field.encoded(),converterFactory.stringConverter(type, annotations, retrofit));} else if (annotation instanceof FieldMap) {// 如果注解是 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: %s, type);}Type valueType Utils.getSupertype(type, Map.class, Object.class);// 创建 FieldMapParameterHandler 实例return new ParameterHandler.FieldMap(converterFactory.stringConverter(valueType, annotations, retrofit));} else if (annotation instanceof Part) {// 如果注解是 Part 类型if (!isMultipart) {throw parameterError(method, p, Part parameters can only be used with multipart encoding.);}Part part (Part) annotation;String partName part.value();if (!.equals(partName) !partName.endsWith(;)) {partName partName ;;}// 创建 PartParameterHandler 实例return new ParameterHandler.Part(partName,converterFactory.requestBodyConverter(type, annotations, methodAnnotations, retrofit));} else if (annotation instanceof PartMap) {// 如果注解是 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: %s, type);}Type valueType Utils.getSupertype(type, Map.class, Object.class);// 创建 PartMapParameterHandler 实例return new ParameterHandler.PartMap(converterFactory.requestBodyConverter(valueType, annotations, methodAnnotations, retrofit));}return null;} }4.3.1 详细解析逻辑 Path 注解解析 首先从 Path 注解中获取占位符名称检查该占位符是否存在于之前解析得到的 relativeUrlParamNames 列表中。如果不存在会抛出异常确保路径占位符的正确性。接着检查参数类型是否包含不可解析的类型变量或通配符。如果存在也会抛出异常因为 Path 参数类型应该是基本类型或字符串。最后创建 ParameterHandler.Path 实例该实例负责处理路径占位符的替换。converterFactory.stringConverter 方法用于创建一个将参数类型转换为字符串的转换器以便将参数值正确地替换到路径中。 Query 注解解析 对于 Query 注解同样会检查参数类型是否包含不可解析的类型变量或通配符。然后创建 ParameterHandler.Query 实例该实例会将参数值作为查询参数添加到 URL 中。converterFactory.stringConverter 用于将参数值转换为字符串形式。 QueryMap 注解解析 先检查参数类型是否为 Map 类型如果不是会抛出异常。接着检查 Map 的键类型是否为 String 类型若不是也会抛出异常。最后创建 ParameterHandler.QueryMap 实例该实例会将 Map 中的键值对作为查询参数添加到 URL 中。converterFactory.stringConverter 用于将 Map 的值转换为字符串。 Header 注解解析 检查参数类型是否包含不可解析的类型变量或通配符。创建 ParameterHandler.Header 实例该实例会将参数值作为请求头添加到请求中。converterFactory.stringConverter 用于将参数值转换为字符串形式的请求头值。 HeaderMap 注解解析 检查参数类型是否为 Map 类型以及 Map 的键类型是否为 String 类型。创建 ParameterHandler.HeaderMap 实例该实例会将 Map 中的键值对作为请求头添加到请求中。converterFactory.stringConverter 用于将 Map 的值转换为字符串形式的请求头值。 Body 注解解析 检查当前请求是否为表单编码或多部分请求如果是则抛出异常因为 Body 参数不能与表单或多部分编码同时使用。创建 ParameterHandler.Body 实例该实例会将参数作为请求体发送。converterFactory.requestBodyConverter 用于将参数类型转换为 RequestBody 类型以便进行网络传输。 Field 注解解析 检查当前请求是否为表单编码请求如果不是则抛出异常因为 Field 参数只能用于表单编码请求。检查参数类型是否包含不可解析的类型变量或通配符。创建 ParameterHandler.Field 实例该实例会将参数值作为表单字段添加到请求体中。converterFactory.stringConverter 用于将参数值转换为字符串形式的表单字段值。 FieldMap 注解解析 检查当前请求是否为表单编码请求以及参数类型是否为 Map 类型Map 的键类型是否为 String 类型。创建 ParameterHandler.FieldMap 实例该实例会将 Map 中的键值对作为表单字段添加到请求体中。converterFactory.stringConverter 用于将 Map 的值转换为字符串形式的表单字段值。 Part 注解解析 检查当前请求是否为多部分请求如果不是则抛出异常因为 Part 参数只能用于多部分请求。处理 Part 注解的 value 属性确保其格式正确。创建 ParameterHandler.Part 实例该实例会将参数作为多部分请求的一部分添加到请求体中。converterFactory.requestBodyConverter 用于将参数类型转换为 RequestBody 类型。 PartMap 注解解析 检查当前请求是否为多部分请求以及参数类型是否为 Map 类型Map 的键类型是否为 String 类型。创建 ParameterHandler.PartMap 实例该实例会将 Map 中的键值对作为多部分请求的多个部分添加到请求体中。converterFactory.requestBodyConverter 用于将 Map 的值转换为 RequestBody 类型。 4.4 创建 RequestFactory 实例 在完成所有参数注解的解析后会调用 RequestFactory.Builder 的 build 方法来构建 RequestFactory 实例 java RequestFactory build() {return new RequestFactory(this); }RequestFactory 类封装了所有解析得到的请求信息包括请求方法、请求路径、请求头、请求体等后续会根据这些信息创建实际的 Request 对象。 4.5 创建 CallAdapter 和 Converter 实例 在 ServiceMethod.parseAnnotations 方法中还会创建 CallAdapter 和 Converter 实例 java // 创建 CallAdapter 实例用于将 Call 对象转换为其他类型 CallAdapterT, ? callAdapter createCallAdapter(retrofit, method, returnType, requestFactory); // 获取响应类型 Type responseType callAdapter.responseType(); if (Utils.hasUnresolvableType(responseType)) {throw methodError(method, Call return type must not include a type variable or wildcard: %s, returnType); }// 创建 Converter 实例用于将响应数据转换为指定类型 ConverterResponseBody, T responseConverter createResponseConverter(retrofit, method, responseType);4.5.1 CallAdapter 实例创建 createCallAdapter 方法通过 Retrofit 实例的 callAdapter 方法从 CallAdapter.Factory 列表中查找合适的 CallAdapter.Factory并调用其 get 方法创建 CallAdapter 实例。CallAdapter 的作用是将 Call 对象转换为其他类型例如将 CallResponse 转换为 ObservableResponse 等以支持不同的异步编程模型。 4.5.2 Converter 实例创建 createResponseConverter 方法通过 Retrofit 实例的 responseBodyConverter 方法从 Converter.Factory 列表中查找合适的 Converter.Factory并调用其 responseBodyConverter 方法创建 Converter 实例。Converter 的作用是将 ResponseBody 转换为指定的响应类型例如将 JSON 数据转换为 Java 对象。 4.6 创建 ServiceMethod 实例 最后根据前面解析得到的信息创建 ServiceMethod 实例 java // 获取 OkHttpClient 实例 okhttp3.Call.Factory callFactory retrofit.callFactory(); // 创建 ServiceMethod 实例 return new HttpServiceMethod(callFactory, requestFactory, callAdapter, responseConverter);HttpServiceMethod 是 ServiceMethod 的具体实现类它负责执行实际的 HTTP 请求并处理响应结果。在 invoke 方法中会根据 RequestFactory 创建 Request 对象使用 OkHttpClient 发送请求然后通过 CallAdapter 和 Converter 处理响应。 java final class HttpServiceMethodResponseT, ReturnT extends ServiceMethodReturnT {private final okhttp3.Call.Factory callFactory;private final RequestFactory requestFactory;private final CallAdapterResponseT, ReturnT callAdapter;private final ConverterResponseBody, ResponseT responseConverter;HttpServiceMethod(okhttp3.Call.Factory callFactory, RequestFactory requestFactory,CallAdapterResponseT, ReturnT callAdapter,ConverterResponseBody, ResponseT responseConverter) {this.callFactory callFactory;this.requestFactory requestFactory;this.callAdapter callAdapter;this.responseConverter responseConverter;}OverrideNullable ReturnT invoke(Object[] args) {// 创建 OkHttp 的 Request 对象Request request requestFactory.create(args);// 创建 OkHttp 的 Call 对象okhttp3.Call call callFactory.newCall(request);// 调用 CallAdapter 的 adapt 方法将 Call 对象转换为指定类型return callAdapter.adapt(new OkHttpCall(request, callFactory, responseConverter));} }五、注解解析后的使用 当 ServiceMethod 实例创建完成后就可以使用它来发起 HTTP 请求了。在调用服务接口的方法时实际上是调用 ServiceMethod 的 invoke 方法 java public interface ApiService {GET(users/{id})CallUser getUser(Path(id) int userId); }// 创建 Retrofit 实例 Retrofit retrofit new Retrofit.Builder().baseUrl(https://api.example.com/).addConverterFactory(GsonConverterFactory.create()).build();// 创建服务代理对象 ApiService apiService retrofit.create(ApiService.class);// 发起请求 CallUser call apiService.getUser(1); call.enqueue(new CallbackUser() {Overridepublic void onResponse(CallUser call, ResponseUser response) {if (response.isSuccessful()) {User user response.body();// 处理响应数据} else {// 处理请求失败}}Overridepublic void onFailure(CallUser call, Throwable t) {// 处理请求异常} });在上述代码中apiService.getUser(1) 实际上调用了 ServiceMethod 的 invoke 方法该方法会根据之前解析得到的注解信息创建 Request 对象使用 OkHttpClient 发送请求并通过 CallAdapter 和 Converter 处理响应结果。 六、总结 Retrofit 的注解定义与解析模块是其核心功能之一通过使用注解开发者可以以一种简洁、声明式的方式定义 HTTP 请求。在解析过程中Retrofit 利用 Java 的反射机制在运行时获取方法和参数上的注解信息并根据注解类型进行相应的处理。具体步骤包括解析请求方法和路径注解、解析参数注解、创建 RequestFactory、CallAdapter 和 Converter 实例最终创建 ServiceMethod 实例来执行实际的 HTTP 请求。这种设计使得 Retrofit 具有高度的灵活性和可扩展性开发者可以通过自定义 CallAdapter.Factory 和 Converter.Factory 来满足不同的需求。同时注解的使用也使得代码更加清晰、易读和易于维护提高了开发效率。
http://www.ho-use.cn/article/10812207.html

相关文章:

  • 比较好的网站开发服务商网站开发用了哪些知识要点
  • 公司网站要备案么wordpress 幻灯代码
  • 网站制作公司去哪找外资企业可以在中国境内做网站吗
  • 毕业设计是做网站设计移动端首页设计
  • 一些建筑设计网站电子商务名词解释
  • 网站注册免费永久网站开发视频资源放哪儿
  • 电商网站建设开发seo网站结构
  • 360网站做二维码中山网站设计收费标准
  • 自己做网站很难公司变更名字需要什么手续
  • 做百度推广网站得多少钱网站建设明细表
  • 网站建设项目进展情况网站内容更改教程
  • 工作网站建设中布线费用账务处理专门做包包的网站
  • 网站建设维护公司地址wordpress 百度软件
  • 12306网站学生做如何查看小程序的开发公司
  • 高质量的集团网站建设重庆网站建设解决方案及流程
  • 可以做软文的网站聊城网站建设首选天成网络
  • 前端网站开发框架广告制作公司经营范围有哪些
  • 人才招聘网站模板html微信小程序开发教程书
  • 哪个做网站wordpress数据结构
  • 本地主机做网站服务器wordpress 搜索 标题 内容
  • 找工作哪个网站好智联招聘网站建设与管理教程视频
  • 信阳做网站的江苏建设网官方网站
  • 本地手机网站建设学校网站建设需求分析
  • 通信部门网站备案证明建筑工程 网络图
  • php 公司网站水果网站模板
  • 网站建设的费用报价高端网站推广
  • 公司注册网站有什么好处求职简历在哪个网站做
  • 奉贤集团公司网站建设wordpress 添加用户组
  • 如何免费自己做个网站临沂门户网站制作
  • 网站备案 不关站wordpress实现动态功能