OkHttp
OkHttp是一个优秀的网络请求框架,在使用需要添加相应的依赖:
implementation "com.squareup.okhttp3:okhttp:3.11.0"
还有请求网络的权限:
GET请求
使用OkHttp进行Get
请求只需要四步即可完成。
// 构建OkHttpClient对象
OkHttpClient client = new OkHttpClient();
// 构造Request对象
Request request = new Request.Builder()
.url("www.baidu.com")
.get()
.build();
//将Request封装为Call
Call call = client.newCall(request);
最后,根据需要调用同步或者异步请求方法即可
同步调用
//同步调用,返回Response,会抛出IO异常
Response response = call.execute();
异步调用
//异步调用,并设置回调函数
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Toast.makeText(OkHttpActivity.this, "get failed", Toast.LENGTH_SHORT).show();
}
@Override
public void onResponse(Call call, final Response response) throws IOException {
final String res = response.body().string();
runOnUiThread(new Runnable() {
@Override
public void run() {
contentTv.setText(res);
}
});
}
});
在使用OkHttp需要注意:
同步调用会阻塞主线程,一般不适用
异步调用的回调函数是在子线程,需要借助于 runOnUiThread() 方法或者Handler来处理。
POST提交键值对
使用OkHttp进行Post
请求和进行Get
请求很类似,只需要五步即可完成。
// 构建OkHttpClient对象
OkHttpClient client = new OkHttpClient();
// 构建FormBody传入参数
FormBody formBody = new FormBody.Builder()
.add("username", "admin")
.add("password", "admin")
.build();
// 构造Request对象,将FormBody作为Post方法的参数传入
Request request = new Request.Builder()
.url("https:www.baidu.com")
.post(formBody)
.build();
//将Request封装为Call
Call call = client.newCall(request);
最后,调用请求,重写回调方法:
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Toast.makeText(OkHttpActivity.this, "Post Failed", Toast.LENGTH_SHORT).show();
}
@Override
public void onResponse(Call call, Response response) throws IOException {
final String res = response.body().string();
runOnUiThread(new Runnable() {
@Override
public void run() {
contentTv.setText(res);
}
});
}
});
POST提交字符串
POST提交字符串就需要使用RequestBody,其中FormBody是RequestBody的子类。
// 构建OkHttpClient对象
OkHttpClient client = new OkHttpClient();
// 构建FormBody传入参数
RequestBody requestBody = RequestBody.create(MediaType.parse("text/plain;charset=utf-8"), "1111111111111111");
// 构造Request对象,将FormBody作为Post方法的参数传入
Request request = new Request.Builder()
.url("www.baidu.com")
.post(requestBody)
.build();
//将Request封装为Call
Call call = client.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
}
});
上面的MediaType我们指定传输的是纯文本,而且编码方式是utf-8,通过上面的方式我们就可以向服务端发送json字符串。
POST上传文件
这里我们以上传一张图片为例,演示OkHttp上传单文件:
OkHttpClient okHttpClient = new OkHttpClient();
File file = new File(Environment.getExternalStorageDirectory(), "1.png");
RequestBody requestBody = RequestBody.create(MediaType.parse("multipart/form-data"),file);
Request request = new Request.Builder()
.url("www.baidu.com")
.post(requestBody)
.build();
Call call = okHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
}
});
如果是多文件上传,可以使用表单的方式来提交:
List<String> fileNames = new ArrayList<>();
fileNames.add(Environment.getExternalStorageState() + "/1.png");
fileNames.add(Environment.getExternalStorageState() + "/2.png");
OkHttpClient okHttpClient = new OkHttpClient();
MultipartBody.Builder builder = new MultipartBody.Builder().setType(MultipartBody.FORM);
for (String fileName : fileNames) {
File file = new File(fileName);
builder.addFormDataPart("files", file.getName(), RequestBody.create(
MediaType.parse("multipart/form-data"), file));
}
MultipartBody multipartBody = builder.build();
Request request = new Request.Builder()
.url("www.baidu.com")
.post(multipartBody)
.build();
Call call = okHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
}
});
POST提交表单
其中,MultipartBody是RequestBody的子类,提交表单需要使用它来构建RequestBody。
File file = new File(Environment.getExternalStorageDirectory(), "1.png");
OkHttpClient okHttpClient = new OkHttpClient();
RequestBody requestBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("username", "admin")
.addFormDataPart("password", "admin")
.addFormDataPart("file", file.getName(),
RequestBody.create(MediaType.parse("application/octet-stream"), file))
.build();
Request request = new Request.Builder()
.url("www.baidu.com")
.post(requestBody)
.build();
Call call = okHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
}
});
GET下载文件
下面将演示OkHttp使用GET请求下载文件的实例:
OkHttpClient okHttpClient = new OkHttpClient();
Request request = new Request.Builder()
.url("www.baidu.com/1.png")
.get()
.build();
Call call = okHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
InputStream inputStream = response.body().byteStream();
int len;
File file = new File(Environment.getExternalStorageDirectory(), "1.png");
FileOutputStream fos = new FileOutputStream(file);
byte[] buf = new byte[128];
while ((len = inputStream.read(buf)) != -1){
fos.write(buf, 0, len);
}
fos.flush();
fos.close();
inputStream.close();
}
});
可以通过流的读取来实现文件的上传和下载进度显示。
OkHttp拦截器
OkHttp的拦截器有五种内置的,除此之外还可以自定义拦截器。
- retryAndFollowUpInterceptor:重试和重定向拦截器,主要负责网络失败重连。
- BridgeInterceptor:主要负责添加交易请求头。
- CacheInterceptor:缓存拦截器,主要负责拦截缓存。
- ConnectInterceptor:网络连接拦截器,主要负责正式开启http请求。
- CallServerInterceptor:负责发送网络请求和读取网络响应
这里主要介绍使用自定义日志拦截器来打印Logger信息。
1)创建HttpLogger类实现HttpLoggingInterceptor.Logger
public class HttpLogger implements HttpLoggingInterceptor.Logger {
@Override
public void log(String message) {
Log.e("HttpLogInfo", message);
}
}
2) 使用OkHttpClient.Builder添加拦截器
// Add Logger Interceptor
HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(new HttpLogger());
loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BASIC);
clientBuilder.addNetworkInterceptor(loggingInterceptor);
这样,就可以在请求网络的时候看到OkHttp的日志信息。
关于OkHttp还有很多内容,这里只是简单的介绍使用。