Retrofit中@Body的使用

关于Retrofit的参数标签@Field、@Path、@Query等等的使用网上已经有很多文章了,可是关于@Body的使用不仅少而且还都是略微的带过,这里就说下Body的用法。

首先@Body的作用是把对象转换成需要的字符串发送到服务器,明白这一点就能对应实际的需要了,比如服务端需要的是关于某一个自定义对象的JSON数据格式,当然服务端若也是Java开发的,那这段JSON能通过工具能自动生成想要的对象,额,其他语言的也能;说了些题外话,主要想说明对象转字符串,当然转化就需要有个转换器——Converter,这个Converter是一个接口,由Retrofit提供,我们定义一个类WrapperConverter implements Converter,如下:

public class WrapperConverter implements Converter {
    private static final String CHARSET_DEFAULT = "utf-8";
    private Gson gson;

    @Override
    public Object fromBody(TypedInput body, Type type) throws ConversionException {
		...
		return obj;
    }

	public Gson getGson(){
        if (gson==null)gson = new Gson();
        return gson;
    }
	
    @Override
    public TypedOutput toBody(Object o) {
        if (o instanceof List) {
            try {
                String postNames = o.toString();
                postNames = postNames.substring(1, postNames.length() - 1);
                return new ArrayTypedOutPut(postNames.getBytes(CHARSET_DEFAULT), CHARSET_DEFAULT);
            } catch (UnsupportedEncodingException e) {
                throw new AssertionError(e);
            }
        } else {
            try {
                return new JsonTypedOutPut(getGson().toJson(o).getBytes(CHARSET_DEFAULT), CHARSET_DEFAULT);
            } catch (UnsupportedEncodingException e) {
                throw new AssertionError(e);
            }
        }
    }

    private static class JsonTypedOutPut implements TypedOutput {
        private final byte[] jsonBytes;
        private final String mimeType;

        public JsonTypedOutPut(byte[] jsonBytes, String encode) {
            this.jsonBytes = jsonBytes;
            this.mimeType = "application/json; charset=" + encode;
        }

        @Override
        public String fileName() {
            return null;
        }

        @Override
        public String mimeType() {
            return mimeType;
        }

        @Override
        public long length() {
            return jsonBytes.length;
        }

        @Override
        public void writeTo(OutputStream out) throws IOException {
            out.write(jsonBytes);
        }
    }

    private static class ArrayTypedOutPut implements TypedOutput {

        private final byte[] arrayBytes;
        private final String mimeType;

        public ArrayTypedOutPut(byte[] arrayBytes, String encode) {
            this.arrayBytes = arrayBytes;
            this.mimeType = "application/text; charset=" + encode;
        }

        @Override
        public String fileName() {
            return null;
        }

        @Override
        public String mimeType() {
            return mimeType;
        }

        @Override
        public long length() {
            return arrayBytes.length;
        }

        @Override
        public void writeTo(OutputStream out) throws IOException {
            out.write(arrayBytes);
        }
    }
}

fromBody是处理接收数据的,就比如像上面说的从JSON转换成Object,这个不是这里要说的重点;看toBody函数,这个函数里面就是处理对象转换字符串(当然不仅限于字符串),代码中的toBody可以把元素为String的List转成逗号分隔的字符串或者将Object转成JSON;好了,基础工作做完了,看下怎么在interface里面使用:

@POST("add")
void GG(@Body List ggs, Callback<String> callback)
@PUT("add")
void GG(@Body List mms, Callback<String> callback)
注意:@Body不能与@FormUrlEncoded共用,否则报错;而@Field偏偏是提交表单使用的,需要@FormUrlEncoded,这很明白了,根据数学的某个公理得出@Body和@Field也是不能同时使用的。

在Retrofit的定义中,POST、PUT、、PATCH请求允许使用Body,如果我们的DELETE请求想使用Body是不被通过的,怎么办呢,用我们自定义的DELETE注释。下面是一源码,可以参考:

@Documented
@Target(METHOD)
@Retention(RUNTIME)
@RestMethod(value = "DELETE", hasBody = true)
public @interface DELETE {
    String value();
}
这是自定义的,Retrofit提供的DELETE没有hasBody = true,也就说它内部对DELETE的处理默认是不接收Body的,按上面做就行了


以上的处理都是基于Retrofit1.9的,2.0也有对应的转化器部分,自行解决就好

若有不恰当的地方,欢迎拍砖


如果您使用Retrofit发送POST请求@Body方式处理数据库参数,可以按照以下步骤进行操作: 1. 创建一个Java类,用于存储参数。例如,如果您要向数据库添加一条用户记录,可以创建一个名为User的Java类,其属性包括用户名,密码等等。 ```java public class User { private String username; private String password; public User(String username, String password) { this.username = username; this.password = password; } public String getUsername() { return username; } public String getPassword() { return password; } } ``` 2. 在Retrofit接口定义POST请求,使用@Body注解将User对象作为请求体发送到服务器。 ```java public interface ApiService { @POST("users") Call<Void> createUser(@Body User user); } ``` 3. 在应用使用Retrofit对象创建接口实例,并调用createUser方法。 ```java // 创建Retrofit对象 Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://example.com/api/") .addConverterFactory(GsonConverterFactory.create()) .build(); // 创建接口实例 ApiService apiService = retrofit.create(ApiService.class); // 创建User对象 User user = new User("username", "password"); // 发送POST请求 Call<Void> call = apiService.createUser(user); call.enqueue(new Callback<Void>() { @Override public void onResponse(Call<Void> call, Response<Void> response) { // 请求成功 } @Override public void onFailure(Call<Void> call, Throwable t) { // 请求失败 } }); ``` 上述代码将向服务器发送一条POST请求,将User对象作为请求体发送到服务器。如果请求成功,服务器将会将User对象存储到数据库。如果请求失败,将会调用onFailure方法。
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值
>