接下来是对RequestBody抽象类的分析,因为内部实现很简单,所以这里贴出加注释的源码,供大家阅读。对于RequestBody抽象类,我们只需要细看最后两个有具体实现的方法。
RequestBody类主要做了获得请求体的数据类型、获得请求体的数据长度、将请求体写入到流中这三件事。
我们看一下它的源码。
1、两个抽象方法
//获取请求体的类型
public abstract MediaType contentType();
//将请求正文写到指定的输出流中
public abstract void writeTo(BufferedSink sink) throws IOException;
因为正文内容的类型是由用户定义的,所以这里将它写成抽象的,又因为正文内容的类型不同,影响到将正文写到指定输出流的具体实现,所以将writeTo(……)写成抽象,让用户自己实现。
2、获取请求正文的内容长度
//获取请求体的数据长度
public long contentLength() throws IOException {
return -1;
}
这个方法没有写成抽象,是因为它的具体实现不会影响到RequestBody能不能用,但是一般这个方法都会在子类中复写。
3、实例化RequestBody抽象类
//创建指定类型的请求正文,类型的选择需要根据想要上传的数据而定的。
public static RequestBody create(MediaType contentType, String content) {
}
public static RequestBody create(final MediaType contentType, final byte[] content) {
}
//上面两个方法最终会调用这个放方法
public static RequestBody create(final MediaType contentType, final byte[] content,
final int offset, final int byteCount) {
if (content == null) throw new NullPointerException("content == null");
Util.checkOffsetAndCount(content.length, offset, byteCount);
return new RequestBody() {
@Override public MediaType contentType() {
return contentType; //字节数组数据的类型
}
@Override public long contentLength() {
return byteCount; //字节数组的长度
}
@Override public void writeTo(BufferedSink sink) throws IOException {
sink.write(content, offset, byteCount); //将字节数组写入流中
}
};
}
//一般实现上传文件的时候调用
public static RequestBody create(final MediaType contentType, final File file) {
if (file == null) throw new NullPointerException("content == null");
return new RequestBody() {
@Override public MediaType contentType() {
return contentType; //文件的类型
}
@Override public long contentLength() {
return file.length(); //获得文件的大小
}
@Override public void writeTo(BufferedSink sink) throws IOException {
Source source = null;
try {
source = Okio.source(file); //获得指定文件的读取流
sink.writeAll(source); //写入文件的读取流
} finally {
Util.closeQuietly(source);
}
}
};
通过上面的方法我们可以创建出我们想要的任何类型的请求正文。
4、RequestBody的两个子类
FormBody(表单)类:
用于实现一般键值(都是字符串类型)对的上传。
主要通过两个List集合来存储动态增加的键和值,最后一次性写入输入流的缓存区。
MultipartBody(多部分类):
1、提到“部分”,要说Http的“多部分上传”,每一“部分”都包含请求头(可有可无)和请求体,“部分”可以看作是一个简略版的小报文(小请求),只不过这里的报文首部字段只能用实体首部字段。
2、“部分”这一概念通过MultipartBody类的内部类Part来具体实现。
3、通过集合的方式存储动态添加的“部分”。
关于首部字段不太明白的朋友,请参见Http首部的字段及相应的取值内容
学习心得:观看资料 + 思考问题 + 实践证明 + 总结概括 + 整理记录 = 有思想的技术大牛。