前言
okhttp无疑Android端最火热的网络请求框架了,由Square公司贡献。
下面对以OKHttp3来介绍OKHttp的使用方法。
本人菜鸡水平,写此文章为了加深印象,如果发现错误或不足恳请指正。谢谢
异步和同步的区别
同步请求:发送方发出数据后,等接收方发回响应以后才发下一个数据包的通讯方式。
异步请求:发送方发出数据后,不等接收方发回响应,接着发送下个数据包的通讯方式
添加依赖
implementation 'com.squareup.okhttp3:okhttp:4.2.1'
implementation 'com.squareup.okio:okio:2.2.2'
okio依赖必须有不然会报错
get请求
我们先看一下异步请求
//获取client
OkHttpClient client=new OkHttpClient.Builder().build();
//构建request,这里不写方法的话默认为get()
Request request=new Request.Builder()
.url("http://www.baidu.com")
.build(); //最后一定要build一下
//构建Call
Call call=client.newCall(request);
//异步请求
call.enqueue(new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
Log.d(TAG,"onFailure");
}
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
Log.d(TAG,response.body().string());
Log.d(TAG,Thread.currentThread().getName());
}
});
我们看这个最简单的demo
LoginActivity123: OkHttp http://www.baidu.com/...
logcat打印出来这句话,说明了回调接口的onFailure方法和onResponse执行在子线程,如果想进行UI操作,还需把消息发到主线程进行
我们在看同步的请求
new Thread(new Runnable() {
@Override
public void run() {
//获取client
OkHttpClient client=new OkHttpClient.Builder().build();
//构建request,这里不写方法的话默认为get()
Request request=new Request.Builder()
.url("http://www.baidu.com")
.build(); //最后一定要build一下
//构建Call
Call call=client.newCall(request);
//同步请求
try {
Response response = call.execute();
if (response.isSuccessful()){
Log.d(TAG,"responsecode:"+response.code());
Log.d(TAG,"responseMsg:"+response.message());
Log.d(TAG,"res:"+response.body().string());
//此时在子线程,更新UI需要在主线程
}
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
我们可以看到,前三个步骤和异步请求的方式一样,有区别的地方就是call这个对象执行的方法是enqueue还是execute。
需要注意的:response.body().string()方法也必须放在子线程中。当执行这行代码得到结果后,再跳转到UI线程修改UI
post请求
post请求也分同步请求和异步请求,和get请求的同步异步类似,我们在开发中,用到的大多数是异步请求,所以我们只看一下异步的请求。
//获取client
OkHttpClient client = new OkHttpClient.Builder()
.build();
//创建RequestBody(Form表单)
RequestBody body = new FormBody.Builder()
.add("username", "admin")
.add("password", "123456")
.build();
//构建建Rquest
Request request = new Request.Builder()
.url(url)
.post(body)
.build();
//构建Call
final Call call = client.newCall(request);
//发起请求
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.i(TAG, "onFailure");
}
@Override
public void onResponse(Call call, Response response) throws IOException {
String result = response.body().string();
Log.i(TAG, "onResponse");
}
});
这里我们需要注意的是,当请求方式为post请求时,我们需要把请求方式进行设置,就是post这个方法,并且我们需要请求对象传进去。这里是把表单请求体对象作为post方法的参数。我们来看看这几种:
1.使用FormBody传递键值对参数
这种方式用来上传String类型的键值对
2.使用RequestBody传递Json
MediaType JSON = MediaType.parse("application/json; charset=utf-8");//数据类型为json格式,
String jsonStr = "{\"username\":\"admin\",\"password\":\"123456\"}";//json数据.
RequestBody body1 = RequestBody.create(JSON,jsonStr);
3.使用RequestBody传递File
MediaType fileType = MediaType.parse("File/*");
File file = new File("path");
RequestBody body = RequestBody.create(fileType , file );
4.使用MultipartBody同时传递键值对和File对象
MultipartBody multipartBody =new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("groupId","123")//添加键值对参数
.addFormDataPart("username","admin")
.addFormDataPart("file",file.getName(),RequestBody.create(MediaType.parse("file/*"), file))//添加文件
.build();
以上的这几种方法都是构建requestBody的方法,实现了传递不能类型的对象。
文件下载
InputStream is = null;
FileOutputStream fos = null;
try{
is = response.body().byteStream();//从服务器得到输入流对象
long sum = 0;
File dir = new File("path");
if (!dir.exists()){
dir.mkdirs();
}
File file = new File(dir, filename);//根据目录和文件名得到file对象
fos = new FileOutputStream(file);
byte[] buf = new byte[1024*8];
int len = 0;
while ((len = is.read(buf)) != -1){
fos.write(buf, 0, len);
}
fos.flush();
}catch (Exception e){
e.printStackTrace();
}finally {
if (is!=null)
is.close();
if (fos!=null)
fos.close();
}
Response中可以获取流对象,有了流对象我们就可以自己实现文件的下载,在最后的finally语句块中要把流对象close。
总结
1.response.body().string()本质是输入流的读操作,这行代码必须放在子线程。
2.response.body().string()只能调用一次,在第一次时有返回值,第二次再调用时将会返回null。
3.异步请求不需要开启子线程,enqueue方法会自动将网络请求部分放入子线程中执行。
感谢阅读,欢迎点赞评论!