学而不思则罔,思而不学则殆
【Retrofit】Retrofit原理解析之注解详解篇
Retrofit系列文章
【Retrofit】Retrofit原理解析之使用篇
【Retrofit】Retrofit原理解析之原理篇
【Retrofit】Retrofit原理解析之注解详解篇
【Retrofit】Retrofit原理解析之设计模式总结篇
粗略看一下,Retrofit定义了总共20多个注解。

注解总结
| 注解 | 作用域 | 功能 | 说明 |
|---|---|---|---|
| @GET | 方法 | 发送GET请求 | - |
| @POST | 方法 | 发送POST请求 | 默认必须带有Body,为空则存在长度为0的正文 |
| @Path | 方法参数 | 实现path拼接 | http://localhost:3434/retrofit/user/{username} + fish2 = http://localhost:3434/retrofit/user/fish2 |
| @Query | 方法参数 | query拼接 | http://localhost:3434/retrofit/query + ? + id=2 —> http://localhost:3434/retrofit/query?id=2 |
| @QueryMap | 方法参数 | query拼接 | 一次拼接多个 |
| @QueryName | 方法参数 | query拼接 | 一次拼接多个 |
| @Header | 方法参数 | 添加请求头 | 一次添加一个 |
| @HeaderMap | 方法参数 | 添加请求头 | 一次添加多个 |
| @Headers | 方法 | 添加请求头 | 一次添加多个 |
| @FormUrlEncoded | 方法 | 表示当前是表单编码 | 不能和@Multipart共存 |
| @Field | 方法参数 | 提交一个表单 | 必须和@FormUrlEncoded一起使用,一次添加一个,可以多个参数使用该注解 |
| @FieldMap | 方法参数 | 提交多个表单 | 必须和@FormUrlEncoded一起使用,一次添加多个,可以多个参数使用该注解 |
| @Body | 方法参数 | 添加正文信息 | 不能和@FormUrlEncoded 和 @Multipart共存,该方法注解只能存在一个 |
| @Multipart | 方法 | 表示当前是多部分编码 | 不能和@FormUrlEncoded 共存 |
| @Part | 方法参数 | 一次添加一个正文part | 必须和@Multipart一起使用,方法参数可以存在多个 |
| @PartMap | 方法参数 | 一次添加多个正文part | 必须和@Multipart一起使用,方法参数可以存在多个 |
注解使用范例
服务端代码:https://github.com/aJanefish/ZyServer
构建Retrofit
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(HttpUrl.get("http://localhost:3434/"))
.addConverterFactory(Utils.FACTORY)
.build();
构建Converter.Factory
//Utils
public class Utils {
static final Converter.Factory FACTORY =
new Converter.Factory() {
@Override
public @Nullable
Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
if (type == Blog.class) return new DataAdapter();
return null;
}
@Override
public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
System.out.println("type:" + type + " " + Blog.class);
System.out.println("type:" + type + " " + Blog.class);
if (type == Blog.class) {
return new RequestBodyAdapter();
}
return null;
}
};
static final class RequestBodyAdapter implements Converter<Blog, RequestBody> {
@Override
public RequestBody convert(Blog blog) throws IOException {
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
for (StackTraceElement stackTraceElement : stackTrace) {
System.out.println(stackTraceElement);
}
return RequestBody.create(null, blog.toString());
}
}
static final class DataAdapter implements Converter<ResponseBody, Blog> {
@Override
public Blog convert(ResponseBody responseBody) throws IOException {
String body = responseBody.string();
// FIXME: 2020/11/16 数据处理
return new Blog(body);
}
}
}
@GET
@Documented
@Target(METHOD)
@Retention(RUNTIME)
public @interface GET {
/**
* A relative or absolute path, or full URL of the endpoint. This value is optional if the first
* parameter of the method is annotated with {@link Url @Url}.
*
* <p>See {@linkplain retrofit2.Retrofit.Builder#baseUrl(HttpUrl) base URL} for details of how
* this is resolved against a base URL to create the full endpoint URL.
*/
String value() default "";
}
public interface BlogService {
@GET("retrofit/all.do")
Call<Blog> getAll();
}
Call<Blog> call = blogService.getAll();
服务端信息:
GET http://localhost:3434/retrofit/all.do?null HTTP/1.1
Accept-Encoding: gzip
Connection: keep-alive
Host: localhost:3434
User-Agent: okhttp/3.14.9
客户端信息:
Blog{body='{"code":200,"msg":"OK","des":"all.do","data":[{"id":1,"date":"2020-11-15 10:39:13","author":"fish1","title":"retrofit1","address":"https://gitee.com/zhangyuwxf/retrofit.git","content":"http test1"},{"id":2,"date":"2020-11-15 10:39:13","author":"fish2","title":"retrofit2","address":"https://gitee.com/zhangyuwxf/retrofit.git","content":"http test2"},{"id":3,"date":"2020-11-15 10:39:13","author":"fish3","title":"retrofit3","address":"https://gitee.com/zhangyuwxf/retrofit.git","content":"http test3"},{"id":4,"date":"2020-11-15 10:39:13","author":"fish4","title":"retrofit4","address":"https://gitee.com/zhangyuwxf/retrofit.git","content":"http test4"},{"id":5,"date":"2020-11-15 10:39:13","author":"fish5","title":"retrofit5","address":"https://gitee.com/zhangyuwxf/retrofit.git","content":"http test5"},{"id":6,"date":"2020-11-15 10:39:13","author":"fish6","title":"retrofit6","address":"https://gitee.com/zhangyuwxf/retrofit.git","content":"http test6"},{"id":7,"date":"2020-11-15 10:39:13","author":"fish7","title":"retrofit7","address":"https://gitee.com/zhangyuwxf/retrofit.git","content":"http test7"},{"id":8,"date":"2020-11-15 10:39:13","author":"fish8","title":"retrofit8","address":"https://gitee.com/zhangyuwxf/retrofit.git","content":"http test8"},{"id":9,"date":"2020-11-15 10:39:13","author":"fish9","title":"retrofit9","address":"https://gitee.com/zhangyuwxf/retrofit.git","content":"http test9"},{"id":10,"date":"2020-11-15 10:39:13","author":"fish10","title":"retrofit10","address":"https://gitee.com/zhangyuwxf/retrofit.git","content":"http test10"}]}'}
@POST
@Documented
@Target(METHOD)
@Retention(RUNTIME)
public @interface POST {
/**
* A relative or absolute path, or full URL of the endpoint. This value is optional if the first
* parameter of the method is annotated with {@link Url @Url}.
*
* <p>See {@linkplain retrofit2.Retrofit.Builder#baseUrl(HttpUrl) base URL} for details of how
* this is resolved against a base URL to create the full endpoint URL.
*/
String value() default "";
}
@POST("retrofit/all.do")
Call<Blog> postAll();
Call<Blog> call = blogService.postAll();
服务端信息:
POST http://localhost:3434/retrofit/all.do?null HTTP/1.1
Accept-Encoding: gzip
Connection: keep-alive
Content-Length: 0
Host: localhost:3434
User-Agent: okhttp/3.14.9
注意Content-Length: 0 , 这说明存在正文,只是正文长度为0;这是因为POST默认是有Body的,但是在这个例子中,正文为空,所以框架还是添加了一个长度为0的body.
Request.Builder get() {
...
RequestBody body = this.body;
if (body == null) {
// Try to pull from one of the builders.
if (formBuilder != null) {
body = formBuilder.build();
} else if (multipartBuilder != null) {
body = multipartBuilder.build();
} else if (hasBody) {
// Body is absent, make an empty body.
body = RequestBody.create(null, new byte[0]);
}
}
...
return requestBuilder.url(url).headers(headersBuilder.build()).method(method, body);
}
客户端信息:
Blog{body='{"code":200,"msg":"OK","des":"all.do","data":[{"id":1,"date":"2020-11-15 10:39:13","author":"fish1","title":"retrofit1","address":"https://gitee.com/zhangyuwxf/retrofit.git","content":"http test1"},{"id":2,"date":"2020-11-15 10:39:13","author":"fish2","title":"retrofit2","address":"https://gitee.com/zhangyuwxf/retrofit.git","content":"http test2"},{"id":3,"date":"2020-11-15 10:39:13","author":"fish3","title":"retrofit3","address":"https://gitee.com/zhangyuwxf/retrofit.git","content":"http test3"},{"id":4,"date":"2020-11-15 10:39:13","author":"fish4","title":"retrofit4","address":"https://gitee.com/zhangyuwxf/retrofit.git","content":"http test4"},{"id":5,"date":"2020-11-15 10:39:13","author":"fish5","title":"retrofit5","address":"https://gitee.com/zhangyuwxf/retrofit.git","content":"http test5"},{"id":6,"date":"2020-11-15 10:39:13","author":"fish6","title":"retrofit6","address":"https://gitee.com/zhangyuwxf/retrofit.git","content":"http test6"},{"id":7,"date":"2020-11-15 10:39:13","author":"fish7","title":"retrofit7","address":"https://gitee.com/zhangyuwxf/retrofit.git","content":"http test7"},{"id":8,"date":"2020-11-15 10:39:13","author":"fish8","title":"retrofit8","address":"https://gitee.com/zhangyuwxf/retrofit.git","content":"http test8"},{"id":9,"date":"2020-11-15 10:39:13","author":"fish9","title":"retrofit9","address":"https://gitee.com/zhangyuwxf/retrofit.git","content":"http test9"},{"id":10,"date":"2020-11-15 10:39:13","author":"fish10","title":"retrofit10","address":"https://gitee.com/zhangyuwxf/retrofit.git","content":"http test10"}]}'}
@Path
@Documented
@Retention(RUNTIME)
@Target(PARAMETER)
public @interface Path {
String value();
/**
* Specifies whether the argument value to the annotated method parameter is already URL encoded.
*/
boolean encoded() default false;
}
@GET("retrofit/user/{username}")
Call<Blog> getByName(@Path("username") String username);
Call<Blog> call = blogService.getByName("fish1");
Call<Blog> call = blogService.getByName("fish2");
http://localhost:3434/retrofit/user/{username} + fish2 = http://localhost:3434/retrofit/user/fish2
服务端信息:
GET http://localhost:3434/retrofit/user/fish1?null HTTP/1.1
Accept-Encoding: gzip
Connection: keep-alive
Host: localhost:3434
User-Agent: okhttp/3.14.9
GET http://localhost:3434/retrofit/user/fish2?null HTTP/1.1
Accept-Encoding: gzip
Connection: keep-alive
Host: localhost:3434
User-Agent: okhttp/3.14.9
客户端信息:
Blog{body='{"code":200,"msg":"OK","des":"path fish1","data":[{"id":1,"date":"2020-11-15 10:39:13","author":"fish1","title":"retrofit1","address":"https://gitee.com/zhangyuwxf/retrofit.git","content":"http test1"}]}'}
Blog{body='{"code":200,"msg":"OK","des":"path fish2","data":[{"id":2,"date":"2020-11-15 10:39:13","author":"fish2","title":"retrofit2","address":"https://gitee.com/zhangyuwxf/retrofit.git","content":"http test2"}]}'}
@Query
@Documented
@Target(PARAMETER)
@Retention(RUNTIME)
public @interface Query {
/** The query parameter name. */
String value();
/**
* Specifies whether the parameter {@linkplain #value() name} and value are already URL encoded.
*/
boolean encoded() default false;
}
@GET("retrofit/query")
Call<Blog> query(@Query("id") String id);
Call<Blog> call = blogService.query("2");
Call<Blog> call = blogService.query("2");
- http://localhost:3434/retrofit/query + ? + id=2 —> http://localhost:3434/retrofit/query?id=2
- http://localhost:3434/retrofit/query + ? + id=4 —> http://localhost:3434/retrofit/query?id=4
服务端信息:
GET http://localhost:3434/retrofit/query?id=2 HTTP/1.1
Accept-Encoding: gzip
Connection: keep-alive
Host: localhost:3434
User-Agent: okhttp/3.14.9
GET http://localhost:3434/retrofit/query?id=4 HTTP/1.1
Accept-Encoding: gzip
Connection: keep-alive
Host: localhost:3434
User-Agent: okhttp/3.14.9
客户端信息:
Blog{body='{"code":200,"msg":"OK","des":"path fish2","data":{"id":2,"date":"2020-11-15 10:39:13","author":"fish2","title":"retrofit2","address":"https://gitee.com/zhangyuwxf/retrofit.git","content":"http test2"}}'}
Blog{body='{"code":200,"msg":"OK","des":"path fish2","data":{"id":4,"date":"2020-11-15 10:39:13","author":"fish4","title":"retrofit4","address":"https://gitee.com/zhangyuwxf/retrofit.git","content":"http test4"}}'}
@QueryMap
@Documented
@Target(PARAMETER)
@Retention(RUNTIME)
public @interface QueryMap {
/** Specifies whether parameter names and values are already URL encoded. */
boolean encoded() default false;
}
@GET("retrofit/query")
Call<Blog> queryMap(@QueryMap Map<String, String> map);
HashMap<String, String> map = new HashMap<>();
map.put("id", "2");
map.put("name", "zy");
map.put("age", "28");
Call<Blog> call = blogService.queryMap(map);
服务端信息:
GET http://localhost:3434/retrofit/query?name=zy&id=2&age=28 HTTP/1.1
Accept-Encoding: gzip
Connection: keep-alive
Host: localhost:3434
User-Agent: okhttp/3.14.9
客户端信息:
Blog{body='{"code":200,"msg":"OK","des":"path fish2","data":{"id":2,"date":"2020-11-15 10:39:13","author":"fish2","title":"retrofit2","address":"https://gitee.com/zhangyuwxf/retrofit.git","content":"http test2"}}'}
@QueryName
@Documented
@Target(PARAMETER)
@Retention(RUNTIME)
public @interface QueryName {
/** Specifies whether the parameter is already URL encoded. */
boolean encoded() default false;
}
@GET("retrofit/query")
Call<Blog> queryName(@QueryName List<String> query);
@GET("retrofit/query")
Call<Blog> queryName(@QueryName String... query);
List<String> list = new ArrayList<>();
list.add("id=2");
list.add("name=zy");
list.add("age=28");
list.add("type=list");
Call<Blog> call1 = blogService.queryName(list);
Call<Blog> call2 = blogService.queryName("id=2", "name=zy", "age=28", "type=strings");
服务端信息:
GET http://localhost:3434/retrofit/query?id%3D2&name%3Dzy&age%3D28&type%3Dlist HTTP/1.1
Accept-Encoding: gzip
Connection: keep-alive
Host: localhost:3434
User-Agent: okhttp/3.14.9
GET http://localhost:3434/retrofit/query?id%3D2&name%3Dzy&age%3D28&type%3Dstrings HTTP/1.1
Accept-Encoding: gzip
Connection: keep-alive
Host: localhost:3434
User-Agent: okhttp/3.14.9
客户端信息:
Blog{body='{"code":200,"msg":"OK","des":"path fish2"}'}
Blog{body='{"code":200,"msg":"OK","des":"path fish2"}'}
@Header
@Documented
@Retention(RUNTIME)
@Target(PARAMETER)
public @interface Header {
String value();
}
@GET("retrofit/query?id=4")
Call<Blog> header(@Header("NAME-TAG") String zy, @Header("AGE-TAG") String age, @Header("Accept-Language") String lang);
Call<Blog> call = blogService.header("zy", "28", "zh-CN");
服务端信息:
GET http://localhost:3434/retrofit/query?id=4 HTTP/1.1
AGE-TAG: 28
Accept-Encoding: gzip
Accept-Language: zh-CN
Connection: keep-alive
Host: localhost:3434
NAME-TAG: zy
User-Agent: okhttp/3.14.9
客户端信息:
Blog{body='{"code":200,"msg":"OK","des":"path fish2","data":{"id":4,"date":"2020-11-15 10:39:13","author":"fish4","title":"retrofit4","address":"https://gitee.com/zhangyuwxf/retrofit.git","content":"http test4"}}'}
@HeaderMap
@Documented
@Target(PARAMETER)
@Retention(RUNTIME)
public @interface HeaderMap {}
@GET("retrofit/query?id=4")
Call<Blog> headerMap(@HeaderMap Map<String, String> map);
HashMap<String,String> map = new HashMap<>();
map.put("Accept","ext/plain");
map.put("Accept-Charset","utf-8");
map.put("NAME-TAG","zy");
Call<Blog> call = blogService.headerMap(map);
服务端信息:
GET http://localhost:3434/retrofit/query?id=4 HTTP/1.1
Accept: ext/plain
Accept-Charset: utf-8
Accept-Encoding: gzip
Connection: keep-alive
Host: localhost:3434
NAME-TAG: zy
User-Agent: okhttp/3.14.9
@Headers
@Documented
@Target(METHOD)
@Retention(RUNTIME)
public @interface Headers {
String[] value();
}
@GET("retrofit/query?id=4")
@Headers({"X-Foo: Bar", "X-Ping: Pong", "NAME: zy"})
Call<Blog> headers();
Call<Blog> call = blogService.headers();
服务端信息:
GET http://localhost:3434/retrofit/query?id=4 HTTP/1.1
Accept-Encoding: gzip
Connection: keep-alive
Host: localhost:3434
NAME: zy
User-Agent: okhttp/3.14.9
X-Foo: Bar
X-Ping: Pong
@FormUrlEncoded + @Field
@Documented
@Target(METHOD)
@Retention(RUNTIME)
public @interface FormUrlEncoded {}
@Documented
@Target(PARAMETER)
@Retention(RUNTIME)
public @interface Field {
String value();
/** Specifies whether the {@linkplain #value() name} and value are already URL encoded. */
boolean encoded() default false;
}
@POST("retrofit/login")
@FormUrlEncoded
Call<Blog> login(@Field("username") String username, @Field("password") String password, @Field("tag") String tag);
Call<Blog> call = blogService.login("zhangyu", "123456", "tag+" + System.currentTimeMillis());
服务端信息:
POST http://localhost:3434/retrofit/login?null HTTP/1.1
Accept-Encoding: gzip
Connection: keep-alive
Content-Length: 56
Content-Type: application/x-www-form-urlencoded
Host: localhost:3434
User-Agent: okhttp/3.14.9
username=zhangyu&password=123456&tag=tag%2B1606047792882
@FormUrlEncoded + @FieldMap
@Documented
@Target(PARAMETER)
@Retention(RUNTIME)
public @interface FieldMap {
/** Specifies whether the names and values are already URL encoded. */
boolean encoded() default false;
}
@POST("retrofit/login")
@FormUrlEncoded
Call<Blog> fieldMap(@FieldMap Map<String, String> map);
HashMap<String, String> map = new HashMap<>();
map.put("id", "2");
map.put("name", "zy");
map.put("age", "28");
Call<Blog> call = blogService.fieldMap(map);
服务端信息:
POST http://localhost:3434/retrofit/login?null HTTP/1.1
Accept-Encoding: gzip
Connection: keep-alive
Content-Length: 19
Content-Type: application/x-www-form-urlencoded
Host: localhost:3434
User-Agent: okhttp/3.14.9
name=zy&id=2&age=28
@Body
@Documented
@Target(PARAMETER)
@Retention(RUNTIME)
public @interface Body {}
@POST("retrofit/add")
Call<Blog> addBlog(@Body Blog blog);
Call<Blog> call = blogService.addBlog(new Blog("I am clint Blog!"));
服务端信息:
POST http://localhost:3434/retrofit/add?null HTTP/1.1
Accept-Encoding: gzip
Connection: keep-alive
Content-Length: 29
Host: localhost:3434
User-Agent: okhttp/3.14.9
Blog{body='I am clint Blog!'}
@Multipart + @Part
@Documented
@Target(PARAMETER)
@Retention(RUNTIME)
public @interface Part {
/**
* The name of the part. Required for all parameter types except {@link
* okhttp3.MultipartBody.Part}.
*/
String value() default "";
/** The {@code Content-Transfer-Encoding} of this part. */
String encoding() default "binary";
}
@Multipart
@POST("retrofit/register")
Call<Blog> registerUser(@Part MultipartBody.Part part, @Part("username") RequestBody username, @Part("password") RequestBody password);
File file = new File("samples/build.gradle");
RequestBody photoRequestBody = RequestBody.create(MediaType.parse("text/plain"), file);
MultipartBody.Part photo = MultipartBody.Part.createFormData("fileName", "build.gradle", photoRequestBody);
Call<Blog> call = blogService.registerUser(photo, RequestBody.create(null, "abc"), RequestBody.create(null, "123"));
服务端信息:
POST http://localhost:3434/retrofit/register?null HTTP/1.1
Accept-Encoding: gzip
Connection: keep-alive
Content-Length: 1002
Content-Type: multipart/form-data; boundary=f39f975d-5f5f-4d74-83e6-f7f8947ce749
Host: localhost:3434
User-Agent: okhttp/3.14.9
--f39f975d-5f5f-4d74-83e6-f7f8947ce749
Content-Disposition: form-data; name="fileName"; filename="build.gradle"
Content-Type: text/plain
Content-Length: 495
apply plugin: 'java-library'
dependencies {
implementation project(':retrofit')
implementation project(':retrofit-mock')
implementation project(':retrofit-converters:moshi')
implementation project(':retrofit-converters:gson')
implementation project(':retrofit-converters:simplexml')
implementation project(':retrofit-adapters:rxjava')
implementation deps.mockwebserver
implementation deps.guava
implementation deps.jsoup
compileOnly deps.findBugsAnnotations
}
--f39f975d-5f5f-4d74-83e6-f7f8947ce749
Content-Disposition: form-data; name="username"
Content-Transfer-Encoding: binary
Content-Length: 3
abc
--f39f975d-5f5f-4d74-83e6-f7f8947ce749
Content-Disposition: form-data; name="password"
Content-Transfer-Encoding: binary
Content-Length: 3
123
--f39f975d-5f5f-4d74-83e6-f7f8947ce749--
----------------------------------------------
@Multipart + @PartMap
@Documented
@Target(PARAMETER)
@Retention(RUNTIME)
public @interface PartMap {
/** The {@code Content-Transfer-Encoding} of the parts. */
String encoding() default "binary";
}
@Multipart
@POST("retrofit/register")
Call<Blog> registerUser(@PartMap Map<String, RequestBody> params);
RequestBody requestBody1 = RequestBody.create(MediaType.parse("text/plain"), new File("samples/build.gradle"));
RequestBody requestBody2 = RequestBody.create(MediaType.parse("text/plain"), new File("samples/src/main/java/com/example/test/PartMapTest.java"));
HashMap<String, RequestBody> hashMap = new HashMap<>();
hashMap.put("part1", requestBody1);
hashMap.put("part2", requestBody2);
hashMap.put("part3", RequestBody.create(null, "zy"));
Call<Blog> call = blogService.registerUser(hashMap);
服务端信息:
POST http://localhost:3434/retrofit/register?null HTTP/1.1
Accept-Encoding: gzip
Connection: keep-alive
Content-Length: 2616
Content-Type: multipart/form-data; boundary=95335199-4456-48d3-b076-eadfdfe4a9c5
Host: localhost:3434
User-Agent: okhttp/3.14.9
--95335199-4456-48d3-b076-eadfdfe4a9c5
Content-Disposition: form-data; name="part1"
Content-Transfer-Encoding: binary
Content-Type: text/plain
Content-Length: 495
apply plugin: 'java-library'
dependencies {
implementation project(':retrofit')
implementation project(':retrofit-mock')
implementation project(':retrofit-converters:moshi')
implementation project(':retrofit-converters:gson')
implementation project(':retrofit-converters:simplexml')
implementation project(':retrofit-adapters:rxjava')
implementation deps.mockwebserver
implementation deps.guava
implementation deps.jsoup
compileOnly deps.findBugsAnnotations
}
--95335199-4456-48d3-b076-eadfdfe4a9c5
Content-Disposition: form-data; name="part2"
Content-Transfer-Encoding: binary
Content-Type: text/plain
Content-Length: 1588
package com.example.test;
import okhttp3.*;
import retrofit2.Call;
import retrofit2.Converter;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.http.*;
import javax.annotation.Nullable;
import java.io.File;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;
public class PartMapTest {
public static void main(String[] args) {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(HttpUrl.get("http://localhost:3434/"))
.addConverterFactory(Utils.FACTORY)
.build();
BlogService blogService = retrofit.create(BlogService.class);
try {
RequestBody requestBody1 = RequestBody.create(MediaType.parse("text/plain"), new File("samples/build.gradle"));
RequestBody requestBody2 = RequestBody.create(MediaType.parse("text/plain"), new File("samples/src/main/java/com/example/test/PartMapTest.java"));
HashMap<String, RequestBody> hashMap = new HashMap<>();
hashMap.put("part1", requestBody1);
hashMap.put("part2", requestBody2);
hashMap.put("part3", RequestBody.create(null, "zy"));
Call<Blog> call = blogService.registerUser(hashMap);
Response<Blog> response = call.execute();
Blog blog = response.body();
System.out.println(blog);
} catch (IOException e) {
//e.printStackTrace();
}
}
}
--95335199-4456-48d3-b076-eadfdfe4a9c5
Content-Disposition: form-data; name="part3"
Content-Transfer-Encoding: binary
Content-Length: 2
zy
--95335199-4456-48d3-b076-eadfdfe4a9c5--
1970

被折叠的 条评论
为什么被折叠?



