Gradle 引入依赖
implementation 'com.squareup.okhttp3:okhttp:3.14.7'
implementation 'com.squareup.okio:okio:1.17.5'
//1、构建okhttpClient 对象
OkHttpClient okHttpClient = new OkHttpClient();
// 2、 构建request请求对象
Request request = new Request.Builder().url("www.baidu.com").get().build();
// 3、生成call对象
Call call = okHttpClient.newCall(request);
// 4、 发起同步请求,同步请求要放在子线程中
new Thread(new Runnable() {
@Override
public void run() {
try {
Response response = call.execute();
} catch (IOException e){
e.printStackTrace();
}
}
}).start();
如果要主线程中直接使用,不单独新建子线程,可以用异步请求.
//1.构建okHttpClient对象
OkHttpClient okHttpClient = new OkHttpClient();
//2.构建request请求对象
Request request = new Request.Builder().url("www.baidu.com").get().build();
//3.生成call对象
Call call = okHttpClient.newCall(request);
//4.异步请求
call.enqueue(new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
}
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
Log.e(TAG,"okhttp get enqueue:" + response.body().string());
ResponseBody body = response.body();
String string = body.string();
byte[] bytes = body.bytes();
InputStream inputStream = body.byteStream();
}
});
call.enqueue会异步执行,其实,两个回调方法 onFailure 和onResponse都是执行在子线程的,因此想要执行UI操作,需要使用Handle切换到UI线程。
POST请求与GET请求的区别:在构造Requeset对象时,需要多构建一个RequestBody对象,来携带我们提交的数据。
//1.构建okHttpClient对象
OkHttpClient okHttpClient = new OkHttpClient();
//2.构建RequestBody对象
RequestBody body = new FormBody.Builder()
.add("ip", "58.188.54.36")
.build();
//3.构建request请求对象,将RequestBody传入request对象
Request request = new Request.Builder()
.url("www.baidu.com")
.post(body)
.build();
//4.生成call对象
Call call = okHttpClient.newCall(request);
//5.同步请求
new Thread(new Runnable() {
@Override
public void run() {
try {
Response response = call.execute();
Log.e(TAG, "okhttp POST execute" + response.body().string());
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
在构建Request的时候,将get()替换成post(body),并且传入requestBody实例.如果构建Request的时候,不指定请求方法时,默认为GET请求。
//1.构建okHttpClient对象
OkHttpClient okHttpClient = new OkHttpClient();
//2.构建RequestBody对象
RequestBody body = new FormBody.Builder()
.add("ip", "58.188.54.36")
.build();
//3.构建request请求对象,将RequestBody传入request对象
Request request = new Request.Builder()
.url("www.baidu.com")
.post(body)
.build();
//4.生成call对象
Call call = okHttpClient.newCall(request);
//5.异步请求
call.enqueue(new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
}
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
Log.e(TAG, "okhttp POST execute" + response.body().string());
}
});
//1.构建okHttpClient对象
OkHttpClient okHttpClient = new OkHttpClient();
//2.构建RequestBody对象
//2.1 文件类型
MediaType contentType = MediaType.parse("text/x-markdown;charset=utf-8");
//2.2 文件内容 string
String content = "xiaomi";
RequestBody requestBody = RequestBody.create(contentType, content);
//3.构建request请求对象,将RequestBody传入request对象
Request request = new Request.Builder()
.url("www.baidu.com")
.post(requestBody)
.build();
//4.生成call对象
Call call = okHttpClient.newCall(request);
//5.异步请求
call.enqueue(new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
}
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
Log.e(TAG, "okhttp POST execute" + response.body().string());
}
});
打印结果
okHttpPost enqueue:
onResponse:Response{protocol=http/1.1, code=200, message=OK, url=https://api.github.com/markdown/raw}
body:xiaoomi
具体的文件上传示例
首先在SD卡里面创建一个xioami.txt文件,里面的内容为"okhttp"
//1.构建okHttpClient对象
OkHttpClient okHttpClient = new OkHttpClient();
//2.构建RequestBody对象,
//2.1 定义上传文件的文件类型
MediaType contentType = MediaType.parse("text/x-markdown;charset=utf-8");
//文件路径
String filePath = "";
//判断当前文件的类型
if (Environment.getExternalStorageState().equals(contentType)) {
filePath = Environment.getExternalStorageDirectory().getAbsolutePath();
} else {
return null;
}
File file = new File(filePath, "xiaomi.txt");
//2.2 创建requestBody,将文件传入
RequestBody requestBody = RequestBody.create(contentType, file);
//3.构建request请求对象,将RequestBody传入request对象
Request request = new Request.Builder()
.url("www.baidu.com")
.post(requestBody)
.build();
//4.生成call对象
Call call = okHttpClient.newCall(request);
//5.异步请求
call.enqueue(new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
}
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
Log.e(TAG, "okhttp POST execute" + response.body().string());
}
});
看完之后,感觉有点懵逼,怎么构建RequestBody的时候,有的时候用 ReuqestBody.create()来构建,有的时候用FormBody构建?这是为什么呢?
FormBody是RequestBody的子类,FromBody 用于提交表单键值对,能够满足我们平常大部分的开发需求。
//RequestBody:FormBody,表单键值对
RequestBody formBody = new FormBody.Builder()
.add("username", "hfy")
.add("password", "qaz")
.build();
当然除了FormBody之外,RequestBody还有一个子类---MultipartyBody,用于post请求提交复杂类型的请求体.复杂请求体可以同时包含多种类型的请求数据.
//1.构建okHttpClient对象
OkHttpClient okHttpClient = new OkHttpClient();
//2.构建RequestBody对象,
//2.1 定义上传文件的文件类型
MediaType contentType = MediaType.parse("text/x-markdown;charset=utf-8");
MultipartBody requestBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("title", "xiaomi")
.addFormDataPart("dress", "kejiyuan")
.addFormDataPart("image", "xm.jpg", RequestBody.create(contentType,
new File("/sdcard/xiaomi.jpg")))
.build();
//3.构建request请求对象,将RequestBody传入request对象
Request request = new Request.Builder()
.url("www.baidu.com")
.post(requestBody)
.build();
//4.生成call对象
Call call = okHttpClient.newCall(request);
//5.异步请求
call.enqueue(new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
}
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
Log.e(TAG, "okhttp POST execute" + response.body().string());
}
});
在构建RequestBody的时候,使用的MultipartyBody构建的MultipartBody实例,前两个上传的是键值对,第三个上传的是表单.addformDatapart方法的第一个参数是key,第二个是上传文件的名子,第三个参数是需要上传的文件。
问题:
1.如何全局设置超时时长?
2.缓存位置,最大缓存大小呢?
3.要监控App通过okhttp发送的所有请求,以及整个请求的所有耗时时间呢?
//1.构建okHttpClient对象
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.connectTimeout(15, TimeUnit.SECONDS)
.readTimeout(10, TimeUnit.SECONDS)
.writeTimeout(10, TimeUnit.SECONDS)
.cache(new Cache(new File("/sdcard/xiaomi.jpg"),500*1024*1024))
.addInterceptor(new Interceptor() {
@NotNull
@Override
public Response intercept(@NotNull Chain chain) throws IOException {
Request request = chain.request();
String url = request.url().toString();
Log.i(TAG, "intercept: proceed start: url"+ url+ ", at "+System.currentTimeMillis());
Response response = chain.proceed(request);
ResponseBody body = response.body();
Log.i(TAG, "intercept: proceed end: url"+ url+ ", at "+System.currentTimeMillis());
return response;
}
})
.build();
这里通过OK HTTPClient.Builder构建者模式设置了连接,读取,写入的超时时间,缓存cache()方法传入了有缓存目录,缓存大小构成的Cache实例.
同时,使用addInterceptor()方法添加了interceptor实例,重写了interceptor方法.interceptor为拦截器,在执行请求的时候会调用,其中chain.procee(request) 是内部真正请求的过程,是个阻塞过程,执行完毕之后,就会得到response.所以在该前后去当时时间,就可以得知整个请求的耗时。
除了全局设置之外,还可以对单个请求进行设置.
Request request = new Request.Builder()
.url("www.baidu.com")
.post(requestBody)
.addHeader("key","value")
.cacheControl(CacheControl.FORCE_CACHE)
.build();
addHeader()方法添加了请求头
cacheControl(CacheControl.FORCE_NETWORK) 设置此次请求只能使用网络,不能用缓存.
使用call.cancel()可以立马取消一个正在执行的call.当用户离开一个应用时,或者跳转到其他的界面时,使用call.cancel()可以节约网络资源;此外,不管同步或者异步的call都可以取消,也可以通过tag来同时取消多个请求.但构建一个请求的时候,通过request.builder.tag()来分配一个标签,之后就可以用okhttpclient.cancel(tag)来取消所有带标签的请求.
ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1);
private void cancel() {
OkHttpClient okHttpClient = new OkHttpClient.Builder().build();
final Request request = new Request.Builder()
.url("www.baidu.com")
.cacheControl(CacheControl.FORCE_NETWORK)
.build();
Call call = okHttpClient.newCall(request);
executorService.schedule(new Runnable() {
@Override
public void run() {
call.cancel();
}
},10,TimeUnit.MICROSECONDS);
}
call.enqueue(new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
}
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
if (response.cacheResponse() != null) {
Log.e(TAG, "cache" + response.cacheResponse().toString());
} else {
Log.e(TAG, "network" + response.networkResponse().toString());
}
}
});
参考:Android进阶之光
网络请求框架OkHttp3全解系列(一):OkHttp的基本使用