提交之后就是解析不出来 不知道是因为什么 有没有人做过这种的帮忙看一下
1条回答 默认 最新
关注 不知道你这个问题是否已经解决, 如果还没有解决的话:- 关于该问题,我找了一篇非常好的博客,你可以看看是否有帮助,链接:【Demo见真章】将安卓的Retrofit移植到鸿蒙系统上,在鸿蒙系统上实现一套网络请求框架
- 除此之外, 这篇博客: Retrofit源码解析中的 方法注解的解析 部分也许能够解决你的问题, 你可以仔细阅读以下内容或者直接跳转源博客中阅读:
RequestFactory.Builder::parseMethodAnnotation
方法:private void parseMethodAnnotation(Annotation annotation) { if (annotation instanceof DELETE) { parseHttpMethodAndPath("DELETE", ((DELETE) annotation).value(), false); } else if (annotation instanceof GET) { parseHttpMethodAndPath("GET", ((GET) annotation).value(), false); } else if (annotation instanceof HEAD) { parseHttpMethodAndPath("HEAD", ((HEAD) annotation).value(), false); } else if (annotation instanceof PATCH) { parseHttpMethodAndPath("PATCH", ((PATCH) annotation).value(), true); } 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 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; } }
这里对方法注解的处理方式主要可以分为三类:
GET
、POST
等请求方法:调用RequestFactory.Builder::parseHttpMethodAndPath
方法进行处理Headers
的注解:调用RequestFactory.Builder::parseHeaders
方法进行处理Multipart
、FormUrlEncoded
注解:主要是在标记变量中进行记录
我们看下第
1
和2
步是如何处理的。对
GET
、POST
等请求方法的注解解析,使用RequestFactory.Builder::parseHttpMethodAndPath
:private void parseHttpMethodAndPath(String httpMethod, String value, boolean hasBody) { // 1.若已设置过httpMethod,则抛出异常 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; // 若请求方法的注解(如GET)里面没有写值,则结束 if (value.isEmpty()) { return; } // Get the relative URL path and existing query string, if present. // 2.判断请求方法的注解中的值是否合理,不合理则抛出异常 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); } } // 3.记录相对Url;解析并记录注解中的占位符(parsePathParameters方法内部使用了正则表达式) this.relativeUrl = value; this.relativeUrlParamNames = parsePathParameters(value); }
该方法主要做了下面的几件事情:
- 记录 请求方法 及 是否有请求体
- 判断请求方法的注解中的值是否合理,不合理则抛出异常
- 记录相对Url,解析并记录注解中的占位符
我们以
GET
请求方法注解为例,第2
步主要是防止GET
的出现类似"users?sortby={sortby}"
这种值,它希望我们动态设置的参数使用@Query
注解来实现,举一个例子:@GET("/banner") fun getBanners(@Query("type") type: Int): Call<BannerJson>
而不是
@GET("/banner?type={type}") fun getBanners(@Path("type") type: Int): Call<BannerJson>
第
3
步,例如我们的请求方法为interface IUser { @GET("/users/{nickname}") fun getUser(@Path("nickname") nickname: String): Call<User> }
那么计算后的值为
// 相对url this.relativeUrl = "/users/{nickname}" // 也就是{}包裹的值,如果有多个{},那么Set<String>会有多个值 this.relativeUrlParamNames = 包含"nickname"的Set<String>
对
Headers
注解的解析,使用RequestFactory.Builder::parseHeaders
方法:private Headers parseHeaders(String[] headers) { // 这是okhttp3的Headers.Builder Headers.Builder builder = new Headers.Builder(); // 遍历传入的headers for (String header : headers) { int colon = header.indexOf(':'); if (colon == -1 || colon == 0 || colon == header.length() - 1) { throw methodError( method, "@Headers value must be in the form \"Name: Value\". Found: \"%s\"", header); } // 获取Header名和Header值 String headerName = header.substring(0, colon); String headerValue = header.substring(colon + 1).trim(); // 如果Header是"Content-Type",则会进行一些特殊处理 if ("Content-Type".equalsIgnoreCase(headerName)) { try { contentType = MediaType.get(headerValue); } catch (IllegalArgumentException e) { throw methodError(method, e, "Malformed content type: %s", headerValue); } } else { // 将Header添加到builder中 builder.add(headerName, headerValue); } } // 返回okhttp3.Headers return builder.build(); }
该方法主要做的事情:将传入的字符串数组
headers
,构造为okhttp3.Headers
并返回,对于Content-Type
类型的Header
,会进行一些特殊的处理。
如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^解决评论 打赏 举报无用 1
悬赏问题
- ¥15 Pyqt 如何正确的关掉Qthread,并且释放其中的锁?
- ¥30 网站服务器通过node.js部署了一个项目!前端访问失败
- ¥15 WPS访问权限不足怎么解决
- ¥15 java幂等控制问题
- ¥15 海湾GST-DJ-N500
- ¥15 氧化掩蔽层与注入条件关系
- ¥15 Django DRF 如何反序列化得到Python对象类型数据
- ¥15 多数据源与Hystrix的冲突
- ¥15 如何在线硕士了解,广告太多,希望有真实接触过的人回答下?(标签-学习|关键词-在线硕士)
- ¥15 zabbix6.4与frp如何进行联动