我们知道http请求包括三个部分即:状态行,请求首部、请求体。所以一些网络请求框架对数据的组织基本上都围绕着这三个部分进行展开,可谓万变不离其宗。Okhttp当然也不例外,在Okttp中用Request对象和ReqeustBody对象来分表一个请求及其请求所携带的请求体。
如果想了解原码可以在github上下载,地址是:okhttp源码
对应一个http请求来说,是否需要请求体(下文用ReqeustBody表示)是根求的方法来判定的,比如Get请求就不需要请求体,而post请求则需要请求体。
OkHttp请求步骤
1) OkHttpClient:新建一个OkHttpClient实例,用于处理请求。
2) Request:构建请求参数,如url,请求方式,请求参数,header等。
3) Call:生成一个具体请求实例,相当于将请求封装成了任务;两种方式:
call.execute(); //同步方式,会阻塞线程,等待返回结果。
call.enqueue(Callback); //异步方式。
4) Response:结果响应
HttpGet
1.同步http请求
对于同步请求在请求时需要开启子线程,请求成功后需要跳转到UI线程修改UI。
public void getDatasync(){
new Thread(new Runnable() {
@Override
public void run() {
try {
OkHttpClient client = new OkHttpClient();//创建OkHttpClient对象
Request request = new Request.Builder()
.url("http://www.baidu.com")//请求接口。如果需要传参拼接到接口后面。
.build();//创建Request 对象
Response response = null;
response = client.newCall(request).execute();//得到Response 对象
if (response.isSuccessful()) {
Log.d("kwwl","response.code()=="+response.code());
Log.d("kwwl","response.message()=="+response.message());
Log.d("kwwl","res=="+response.body().string());
//此时的代码执行在子线程,修改UI的操作请使用handler跳转到UI线程。
}
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
2.异步http请求
这种方式不用再次开启子线程,但回调方法是执行在子线程中,所以在更新UI时还要跳转到UI线程中。
异步请求的打印结果与注意事项与同步请求时相同。最大的不同点就是异步请求不需要开启子线程,enqueue方法会自动将网络请求部分放入子线程中执行。
private void getDataAsync() {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("http://www.baidu.com")
.build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if(response.isSuccessful()){//回调的方法执行在子线程。
Log.d("kwwl","获取数据成功了");
Log.d("kwwl","response.code()=="+response.code());
Log.d("kwwl","response.body().string()=="+response.body().string());
}
}
});
}
HttpPost
Post请求也分同步和异步两种方式,同步与异步的区别和get方法类似,所以此时只讲解post异步请求的使用方法。
private void postDataWithParame() {
OkHttpClient client = new OkHttpClient();//创建OkHttpClient对象。
FormBody.Builder formBody = new FormBody.Builder();//创建表单请求体
formBody.add("username","zhangsan");//传递键值对参数
Request request = new Request.Builder()//创建Request 对象。
.url("http://www.baidu.com")
.post(formBody.build())//传递请求体
.build();
client.newCall(request).enqueue(new Callback() {。。。});//回调方法的使用与get异步请求相同,此时略。
}
重点是Request.Builder类的post方法,在Request.Builder对象创建最初默认是GET请求,因此在get请求中不需要设置请求方式,当调用post方法时把请求方式修改为POST。
注意:Request.Builder类的post方法,源码如下:
public Builder post(RequestBody body) {
return method("POST", body);
}
public Builder method(String method, @Nullable RequestBody body) {
if (method == null) throw new NullPointerException("method == null");
if (method.length() == 0) throw new IllegalArgumentException("method.length() == 0");
if (body != null && !HttpMethod.permitsRequestBody(method)) {
throw new IllegalArgumentException("method " + method + " must not have a request body.");
}
if (body == null && HttpMethod.requiresRequestBody(method)) {
throw new IllegalArgumentException("method " + method + " must have a request body.");
}
this.method = method;
this.body = body;
return this;
}
由方法的声明可以看出,post方法接收的参数是RequestBody 对象,所以只要是RequestBody 类以及子类对象都可以当作参数进行传递。FormBody就是RequestBody 的一个子类对象。