1. 创建一个OkHttpClient对象,该对象:
构造方法:OkHttpClient client = new OkHttpClient();
如果要添加拦截器,超时等,调用如下构造方法:
okHttpClient client = new OkHttpClient
.Builder()
.readTimeout(int SECONDS,TimeUnit.SECONDS)//设置读取超时时间
.writeTimeout(int SECONDS,TimeUnit.SECONDS)//设置写的超时时间
.connectTimeout(int SECONDS,TimeUnit.SECONDS)//设置连接超时时间
.addInterceptor(appInterceptor)//Application拦截器
.addNetworkInterceptor(networkInterceptor)//Network拦截器
.build();
2. 如果网络请求需要请求体,则需要创建一个RequestBody对象,
RequestBody是一个抽象类,API提供的实现类主要有MultipartBody上传文件和FormBody上传表单两个
FormBody源码中使用两个链表存储键值对,构造方法如下:
RequestBody requestBody = new FormBody.Builder
.add(String name, String value)
.add(String name, String value)
...
.build();
MultipartBody利用静态内部类Part封装请求头(Headers,可以为空)和请求体(RequestBody),
其构造方法为private,提供静态方法获取Part实例
Part提供的静态方法有:
create(RequestBody body)
create(@Nullable Headers headers, RequestBody body)
createFormData(String name, String value)
createFormData(String name, @Nullable String filename, RequestBody body)
MultipartBody利用List
每个Part封装了一个RequestBody
MultipartBody利用静态内部类Builder来创建MultipartBody,和向parts列表中添加Part。
MultipartBody.Builder中的方法有:
addPart(Part part)//其他几个静态方法都将调用此方法
addPart(RequestBody body)//方法内部将RequestBody对象封装成headers为空的Part对象
addPart(@Nullable Headers headers, RequestBody body)
addFormDataPart(String name, String value)//添加表单
addFormDataPart(String name, @Nullable String filename, RequestBody body)
最后MultipartBody.Builder通过build()方法返回MultipartBody对象。
使用示例:
MultipartBody multipartBody =new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("groupId",""+groupId)//添加键值对参数
.addFormDataPart("title","title")
.addFormDataPart("file",file.getName(),RequestBody.create(MediaType.parse("file/*"), file)
.build();
也可以利用RequestBody中的静态方法create(final @Nullable MediaType contentType, content)创建出RequestBody,
create()方法中利用匿名内部类实现了RequestBody,其中content可以是String,byte[],File。
ps:使用byte[]时可以传入一个int型变量作为偏移量,一个int型变量作为发送量,
方法原型:
create(final @Nullable MediaType contentType, final byte[] content,final int offset, final int byteCount)
示例:
MediaType JSON = MediaType.parse("application/json; charset=utf-8");//数据类型为json格式,
String jsonStr = "{\"username\":\"lisi\",\"nickname\":\"李四\"}";//json数据.
RequestBody body = RequestBody.create(JSON, josnStr);
最后还能继承RequestBody创建自己的实现类,该类有三个方法要重写:
public @Nullable MediaType contentType() {}
public long contentLength() throws IOException {}
public void writeTo(BufferedSink sink) throws IOException
{sink.write(content);}//BufferedSink是okhttp通信包中的类,该类使用类似java的输出流
自定义的RequestBody可以实现流的上传
3. 创建一个Request对象,该对象中封装网络请求的参数:
url(网址)
method(POST,GET等)
如果是"GET","HEAD"则不能有请求体
POST,PUT,PATCH,PROPPATCH,REPORT要有请求体。默认是"GET"
headers(请求头,以键值对的形式存储)。
RequestBody(请求体)
构造方法:Request request = new Request.Builder()
.url(String url)
.addHeader(String name, String value)
.removeHeader(String name)
.method(String method, @Nullable RequestBody body)
.build();
如果是发送post请求,可以直接把 .method(String method, @Nullable RequestBody body)换成.post(RequestBody body)
如果是发送get请求,可以直接把 .method(String method, @Nullable RequestBody body)换成.post()
类似的,其他请求也可以这样设置 .head(),delete(@Nullable RequestBody body),delete(),.put(RequestBody body)等
该类就是存参数的。
4. 创建一个Call对象
构造方法:Call call = client.newCall(request);
5. 利用Call对象发出网络请求,获取服务器的回复(封装在Response对象中),发出网络请求有两种方式:
同步方式:
Response reponse = call.execute();
异步方式:(测试发现,onResponse()方法并不运行在主线程中)
call.enqueue(new Callback()
{
@Override
public void onFailure(Call call, IOException e) {}
@Override
public void onResponse(Call call, Response response) throws IOException {} //回调的参数中获取Response
});
每一个Call对象只能发出一次网络请求,否则会抛出异常,源码中Call设置了executed字段,
在execute()和enqueue()方法执行时,首先检查和设置此字段,此操作还使用了synchronized关键字保持同步
6. 利用Response对象读出服务器端的返回结果
Response封装的主要方法如下:
protocol()//返回http协议,例如:HTTP_1_1
code()//返回HTTP的状态码,例如404(Not Found)
isSuccessful()//判断网络请求是否成功,判断依据是ode >= 200 && code < 300
message()//返回Http的状态信息/** Returns the HTTP status message. */
body()//获得ResponseBody响应体对象,最重要
isRedirect()//是否被重定向,判断依据是code
close()//关闭响应,方法里面调用了body.close(),关闭响应体,关闭流
7. 利用Reponse中的ReponseBody对象获取服务器代码返回的内容
MediaType contentType()//获取媒体类型,可能为null
contentLength()//内容长度
InputStream byteStream()//获取输入流,文件传输的重要方法
byte[] bytes()//获取返回体的字节数组,但是返回的响应体长度太大会抛出异常
Reader charStream()//获取java IO的Reader对象
String string()//获取响应体中的字符串
Charset charset()//获取编码的字符集,只有utf-8
void close()//关闭输入流
8. 拦截器的使用:
实现Interceptor接口,该接口只用Response intercept(Chain chain)方法需要实现,
在该方法中调用Chain对象的Response proceed(Request request)方法将请求传到下一个拦截器,
同时会收到网络请求的响应,处理该响应即可。
拦截器使用的核心在与Chain对象
利用Chain中的Request request()方法可以获取原始的请求对象,然后修改请求,例如:修改Request中的统一的参数编码,
利用Chain中的Response proceed(Request request)修改获取响应,将响应统一修改后再返回给上层的拦截器