OkHttp3讲解
01,OkHttp3简介
1.支持http和https协议,api相同,易用;
2.http使用线程池,https使用多路复用;
3.okhttp支持同步和异步调用;
4.支持普通form和文件上传form;
5.操作请求和响应(日志,请求头,body等);
6.okhttp可以设置缓存;
7.支持透明的gzip压缩响应体
思路:
OkHttp3 使用思路
get请求思路
1.获取okHttpClient对象
2.构建Request对象
3.构建Call对象
4.通过Call.enqueue(callback)方法来提交异步请求;execute()方法实现同步请求
post请求思路
1.获取okHttpClient对象
2.创建RequestBody
3.构建Request对象
4.构建Call对象
5.通过Call.enqueue(callback)方法来提交异步请求;execute()方法实现同步请求
1.导入依赖
implementation 'com.squareup.okhttp3:okhttp:3.10.0'
2.get实现请求代码(举例异步实现)
//1.创建OkHttpClient对象
OkHttpClient okHttpClient = new OkHttpClient.Builder().build();
//2.创建Request请求对象
Request build = new Request.Builder()
.get()
.url("http://www.wanandroid.com/article/list/0/json?cid=60")
.build();
//3.创建Call对象
Call call = okHttpClient.newCall(build);
//4.异步
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
String string = response.body().string();
Log.e("zll", "onResponse: "+string);
//这里并不是主线程如果切换线程用一下方法
runOnUiThread(new Runnable() {
@Override
public void run() {
}
});
}
});
3.poth实现请求(举例同步实现)
//接口参数 String username,String password
//第一步创建OKHttpClient
OkHttpClient client = new OkHttpClient.Builder()
.build();
//第二步创建RequestBody
RequestBody body = new FormBody.Builder()
.add("username", "admin")
.add("password", "123456")
.build();
//第三步创建Rquest
Request request = new Request.Builder()
.url("http://yun918.cn/study/public/index.php/login")
.post(body)
.build();
//第四步创建call回调对象
final Call call = client.newCall(request);
//第五步发起请求
new Thread(new Runnable() {
@Override
public void run() {
try {
Response response = call.execute();
String result = response.body().string();
Log.i("response", result);
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
4. 请求头处理(Header)以及超时和缓冲处理以及响应处理
//超时设置
OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(5,TimeUnit.SECONDS)
.readTimeout(5,TimeUnit.SECONDS)
.writeTimeout(5,TimeUnit.SECONDS)
.cache(new Cache(cacheDirectory,1010241024))
.build();
//表单提交
RequestBody requestBody = new FormBody.Builder()
.add("pno", "1")
.add("ps","50")
.add("dtype","son")
.add("key","4a7cf244fd7efbd17ecbf0cb8e4d1c85")
.build();
//请求头设置
Request request = new Request.Builder()
.url(url)
.addHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8")
.header("User-Agent", "OkHttp Example")
.post(body)
.build();
//响应处理
@Override
public void onResponse(Call call, Response response) throws IOException {
//响应行
Log.d("ok", response.protocol() + " " +response.code() + " " + response.message());
//响应头
Headers headers = response.headers();
for (int i = 0; i < headers.size(); i++) {
Log.d("ok", headers.name(i) + ":" + headers.value(i));
}
//响应体
final String string = response.body().string();
Log.d("ok", "onResponse: " + string);
runOnUiThread(new Runnable() {
@Override
public void run() {
tx.setText(string);
}
});
}
4. 请求体处理(Form表单,String字符串,流,文件)
//1.POST方式提交String/JSON application/json;json串
MediaType mediaType1 = MediaType.parse("application/x-www-form-urlencoded;charset=utf-8");
String requestBody = "pno=1&ps=50&dtype=son&key=4a7cf244fd7efbd17ecbf0cb8e4d1c85";
RequestBody requestBody1 = RequestBody.create(mediaType1, requestBody);
//POST方式提交JSON:传递JSON同时设置son类型头
RequestBody requestBodyJson = RequestBody.create(MediaType.parse("application/json;charset=utf-8"), "{要请求的数据需要解析}");
request.addHeader("Content-Type", "application/json")//必须加json类型头
//POST方式提交无参
RequestBody requestBody1 = RequestBody.create(MediaType.parse("application/x-www-form-urlencoded;charset=utf-8"), "");
//2.POST方式提交流
RequestBody requestBody2 = new RequestBody() {
@Nullable
@Override
public MediaType contentType() {
return MediaType.parse("application/x-www-form-urlencoded;charset=utf-8");
}
@Override
public void writeTo(BufferedSink sink) throws IOException {
sink.writeUtf8("pno=1&ps=50&dtype=son&key=4a7cf244fd7efbd17ecbf0cb8e4d1c85");
}
};
//3.POST方式提交表单
RequestBody requestBody4 = new FormBody.Builder()
.add("pno", "1")
.add("ps","50")
.add("dtype","son")
.add("key","4a7cf244fd7efbd17ecbf0cb8e4d1c85")
.build();
//4.POST提交文件
MediaType mediaType3 = MediaType.parse("text/x-markdown; charset=utf-8");
File file = new File("test.txt");
RequestBody requestBody3 = RequestBody.create(mediaType3, file);
//5.POST方式提交分块请求
MultipartBody body = new MultipartBody.Builder("AaB03x")
.setType(MultipartBody.FORM)
.addPart(
Headers.of("Content-Disposition", "form-data; name="title""),
RequestBody.create(null, "Square Logo"))
.addPart(
Headers.of("Content-Disposition", "form-data; name="image""),
RequestBody.create(MediaType.parse("image/png"), new File("website/static/logo-square.png")))
.build();
5.上传文件
1.权限:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
2.要添加动态权限
/**
* 动态获取权限,Android 6.0 新特性,一些保护权限,除了要在AndroidManifest中声明权限,还要使用如下代码动态获取
*/
if (Build.VERSION.SDK_INT >= 23) {
int REQUEST_CODE_CONTACT = 101;
String[] permissions = {Manifest.permission.WRITE_EXTERNAL_STORAGE};
//验证是否许可权限
for (String str : permissions) {
if (this.checkSelfPermission(str) != PackageManager.PERMISSION_GRANTED) {
//申请权限
this.requestPermissions(permissions, REQUEST_CODE_CONTACT);
return;
}
}
}
3.方法使用
private void initData() {
// 1.获取文件
String filePath = Environment.getExternalStorageDirectory() + File.separator + "bb.png";
File file = new File(filePath);
if (file.exists()) {
Log.d(TAG, "exists: " + true);
}
// 2.创建文件上传请求对象
RequestBody fileBody = RequestBody.create(MediaType.parse("image/png"), file);
// 3.new okHttp
OkHttpClient okHttpClient = new OkHttpClient();
// 4.创建多媒体 请求对象
RequestBody multipartBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("key", "png") // 文件上传的参数
.addFormDataPart("file", file.getName(), fileBody)
.build();
//5. 创建request对象
final Request request = new Request.Builder()
.url(url)
.post(multipartBody)
.build();
// 6 获取Call 请求对象
Call call = okHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.d(TAG, "onFailure: ");
}
@Override
public void onResponse(Call call, final Response response) throws IOException {
runOnUiThread(new Runnable() {
@Override
public void run() {
try {
String string = response.body().string();
tv.setText(string);
} catch (IOException e) {
e.printStackTrace();
}
Log.d(TAG, "onResponse: " + "asdklj;aosldj");
}
});
}
});
}
6.上传文件带进度
private void uploadFile() {
// 1.获取文件
String filePath = Environment.getExternalStorageDirectory() + File.separator + "aa.jpg";
final File file = new File(filePath);
if (file.exists()) {
Log.d(TAG, "exists: " + true);
}
// file --reqeustbody
// RequestBody requestBody = RequestBody.create(MediaType.parse("image/jpg"), file);
RequestBody requestBody = new RequestBody() {
@Override
public MediaType contentType() { // 媒体 类型 image/jpg
return MediaType.parse("image/jpg");
}
@Override
public long contentLength() throws IOException { // 上传文件的长度
return file.length();
}
@Override
public void writeTo(BufferedSink sink) throws IOException { // 从文件里通过流的形式写入到sink
Source source;
try {
source = Okio.source(file);
Buffer buf = new Buffer();
long filelength = contentLength();
long isReadSize = 0;// 每次读出的大小
long readCount = 0;// 计算已经写入的长度
while ((isReadSize = source.read(buf, 1024)) != -1) {
sink.write(buf, isReadSize);
// 进度值
readCount += isReadSize;// 计算已经写入的长度
int progress = (int) ((100 * readCount) / filelength);
Log.d(TAG, "writeTo: ==" + progress);
ProgressEvent progressEvent = new ProgressEvent();
progressEvent.position = progress + "";
EventBus.getDefault().post(progressEvent);
}
} catch (Exception e) {
e.printStackTrace();
}
}
};
MultipartBody multipartBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("file", file.getName(), requestBody)
.addFormDataPart("key", "hhh")
.build();
OkHttpClient okHttpClient = new OkHttpClient();
final Request request = new Request.Builder()
.url("http://yun918.cn/study/public/file_upload.php")
.post(multipartBody)
.build();
Call call = okHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.d(TAG, "onFailure: e=" + e.getMessage());
}
@Override
public void onResponse(Call call, Response response) throws IOException {
Log.d(TAG, "onResponse: response=" + response.body().string());
}
});
}
7.下载带进度
private void downLoadFile() {
String filePath = Environment.getExternalStorageDirectory() + File.separator + "download.jpg";
final File file = new File(filePath);
if (!file.exists()) {
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
OkHttpClient okHttpClient = new OkHttpClient();
Request request = new Request.Builder()
.url("http://www.wanandroid.com/blogimgs/50c115c2-cf6c-4802-aa7b-a4334de444cd.png")
.build();
Call call = okHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.d(TAG, "onFailure: e="+e.getMessage());
}
@Override
public void onResponse(Call call, Response response) throws IOException {
//IO InputStream outputStream
InputStream inputStream = response.body().byteStream();
doStream(inputStream, file.getAbsolutePath());
}
});
}
/**
* @param is 输入流 服务器
* @param filePath 本地文件路径
*/
public void doStream(InputStream is, String filePath) {
byte[] buf = new byte[2048];
int len = 0;// 每次读取的长度
FileOutputStream fos = null;
File file = new File(filePath);
try {
long total = file.length();
fos = new FileOutputStream(file);
int sum = 0;
int progress = 0;
while ((len = is.read(buf)) != -1) {
fos.write(buf, 0, len);// 写入 读取的长度
sum += len;
progress = (int) (sum * 100 / total);
ProgressEvent progressEvent = new ProgressEvent();
progressEvent.position = progress + "";
EventBus.getDefault().post(progressEvent);
Log.d(TAG, "progress:= " + progress + "%");
}
// 下载完成
ProgressEvent progressEvent = new ProgressEvent();
if (progress == 100) {
progressEvent.position = "下载完成";
}
EventBus.getDefault().post(progressEvent);
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
is.close();
fos.close();
fos.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}