OkHttp简介

关于Okhttp的简介,相信大家都不陌生了,这里就不讲了。

初级用法

Get请求

比如这里的使用get方法进行登录操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
private void doLoginGet(){
final String url = "xxxxx?username=allever?password=123456"
OkHttpUtil.loginGet(url, new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, final Response response) throws IOException {
handleLogin(response.body().string(););
}
});
}

loginGet方法如下:

1
2
3
4
5
6
7
public static void loginGet(String url, Callback callback){
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(url)
.build();
client.newCall(request).enqueue(callback);
}

是不是很简单,创建OkhttpClient实例,创建请求,然后执行请求,然后进行回调

处理结果

1
2
3
4
5
6
7
8
9
10
11
private void handleLogin(final String result){
runOnUiThread(new Runnable() {
@Override
public void run() {
Gson gson = new Gson();
LoginRoot loginRoot = gson.fromJson(result,LoginRoot.class);
User user = loginRoot.getUser();
tv_result.setText(user.getNickname() + "\n" + user.getSignature());
}
});
}

因为回调方法在子线程中,所以要切回到主线程中,方法有很多,可以使用Handler,这里直接runOnUiThread()就好了。简单起见,另外Gson处理json数据不在讨论范围之内,

Post请求

例子同上,登录操作

1
2
3
4
5
6
7
8
9
10
11
12
13
private void doLoginPost(){
OkHttpUtil.loginPost(username, password, new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
handleLogin(response.body().string());
}
});
}

1
2
3
4
5
6
7
8
9
10
11
12
13
public static void loginPost(String username, String password, Callback callback){
String url = BASE_URL + "LoginServlet";
OkHttpClient client = new OkHttpClient();
FormBody.Builder builder = new FormBody.Builder();
builder.add("username",username);
RequestBody requestBody = builder.build();
Request request = new Request.Builder()
.url(url)
.post(requestBody)
.build();
client.newCall(request).enqueue(callback);
}

唯一不同的就是这里啦,首先还是创建OkhttpClient实例,这里使用了FormBody表单, 用这个表单创建请求体,然后创建请求,最后执行请求,回调
最后的处理方法同上。

异步请求

上面两个例子都是异步请求,因为不用咋们手动开启子线程,它会自动的开启线程去处理的

同步请求

例如,退出登录的例子

1
2
3
private void doLogoutTongBu(){
OkHttpUtil.logoutTongBu(handler);
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public static void logoutTongBu(final Handler handler){
new Thread(new Runnable() {
@Override
public void run() {
String url = "xxxxx/logout";
OkHttpClient client = new OkHttpClient();
FormBody.Builder builder = new FormBody.Builder();
if (!SharePreferenceUtil.getSessionId().equals("")){
RequestBody requestBody = builder.build();
Request request = new Request.Builder()
.url(url)
.post(requestBody)
.addHeader("Cookie", "JSESSIONID=" + SharePreferenceUtil.getSessionId())
.build();
Response response = null;
try {
response = client.newCall(request).execute();
String result = response.body().string();
Message message = new Message();
message.what = MESSAGE_LOGOUT;
message.obj = result;
handler.sendMessage(message);
}catch (IOException ioe){
ioe.printStackTrace();
}
}else {
Message message = new Message();
message.what = MESSAGE_LOGOUT;
message.obj = "未登录";
handler.sendMessage(message);
}
}
}).start();
}

这里手动开启了一个线程进行网络请求,还是使用Post方法,跟上面的没啥区别,注意这里

1
addHeader("Cookie", "JSESSIONID=" + SharePreferenceUtil.getSessionId())

添加Cookie的头部信息,Cookie就是用来持久化用户登录
还有就是执行请求的方法有些区别,同步执行是:

1
response = client.newCall(request).execute();

异步执行是:

1
client.newCall(request).enqueue(callback);

同步执行的结果为Response对象,就是服务器返回的数据

高级用法

上传文件和表单数据

例如发一条说说,包括图片和文字

1
2
3
4
5
6
7
8
9
10
11
12
13
private void doAddNews(String content){
OkHttpUtil.addNews(content, new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
Log.d(TAG, "onResponse: result = " + response.body().string());
}
});
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public static void addNews(String content,Callback callback){
OkHttpClient client = new OkHttpClient();
MultipartBody multipartBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("content",content)
.addFormDataPart("city","番禺")
.addFormDataPart("longitude","111.22")
.addFormDataPart("latitude","22.22")
.addPart(Headers.of("Content-Disposition",
"form-data; name=\"part1"+ "\""),
RequestBody.create(
MediaType.parse("application/octet-stream"),
new File(Environment.getExternalStorageDirectory().getPath()+"/","jiaxin.png")))
.build();
if (SharePreferenceUtil.getSessionId().equals("")){
}
Request request = new Request.Builder()
.url(BASE_URL + "AddNewsServlet")
.post(multipartBody)
.addHeader("Cookie", "JSESSIONID=" + SharePreferenceUtil.getSessionId())
.build();
client.newCall(request).enqueue(callback);
}

设置表单类型

1
setType(MultipartBody.FORM)

使用MultipartBody对象把表单数据和文件数据形式封装,表单使用

1
addFormDataPart("content",content)

用键值对保存

文件用

1
2
3
4
5
.addPart(Headers.of("Content-Disposition",
"form-data; name=\"part1"+ "\""),
RequestBody.create(
MediaType.parse("application/octet-stream"),
fileObject))

其中:part1是服务器根据键找到part的那个键

1
request.getPart("part1");

如果多文件的话就多次调用addPart()

必须设置表单类型

1
setType(MultipartBody.FORM)