行业知识
Android:OkHttp网络请求框架的使用
目录
一,OkHttp简介
二,OkHttp请求处理流程
三,OkHttp环境配置
四,OkHttp的使用
1.get网络请求
2.post上传表单数据
3.post上传json格式数据
4.文件上传
5.文件下载
一,OkHttp简介
OkHttp是square公司推出的一款Android和Java网络请求库,是目前公认的最好用的网络请求框架,OkHttp有以下的特点:
- 支持Http/2,允许对同一主机的所有请求共享同一套接字;
- 使用连接池减少请求延时;
- 透明的GZIP压缩减少响应数据的大小;
- 缓存响应的内容,避免重复请求;
OkHttp源码地址:https://github.com/square/okhttp
二,OkHttp请求处理流程
(1)使用OkHttp需要先创建OkHttpClient对象,可以使用构造器直接创建,也可以使用builder创建;
(2)使用Request.builder创建Request请求,用于封装要访问的网络地址Url。当进行post操作时,还需创建RequestBody用于封装请求数据,并调用Requst的post方法;
(3)通过OkHttpClient的newCall方法创建Call对象,使用同步或异步的方法发送Request请求,并接收Response响应数据;
三,OkHttp环境配置
(1)在build.gradle中添加依赖:
dependencies {
implementation 'com.squareup.okhttp3:okhttp:3.14.9'
}
(2)在AndroidManifest.xml中添加网络访问权限:
(3)在AndroidManifest.xml添加 android:usesCleartextTraffic="true" 解除Http访问禁制:
四,OkHttp的使用
OkHttp主要有以下功能:
- get,post请求文本数据;
- 上传文件;
- 下载文件;
- 加载图片(自动压缩图片大小);
1.get网络请求
private void visitInternet() { //1.创建HttpClient对象 OkHttpClient okHttpClient = new OkHttpClient(); //2.获取request对象 Request.Builder builder = new Request.Builder() .url("https://www.bilibili.com/"); Request request = builder.build(); //3.获取call对象 Call call = okHttpClient.newCall(request); //4.执行网络操作(同步) try { //同步执行网络操作 Response response = call.execute(); String result = response.body().string(); showResultOnUiThread(result); } catch (IOException e) { throw new RuntimeException(e); }} 注意这里使用了call的同步请求方式,会产生阻塞,所以此方法必须放在子线程中执行。如果不想放在子线程中执行的话,可以使用call的异步请求方式。
当请求成功时call会返回Response,我们可以通过response.body()获取字符串,输入流等返回的信息。
2.post上传表单数据
当需要上传数据时,需要创建RequestBody用于封装数据,因为我们这里上传的是表单数据,所以需要创建RequestBody的子类FormBody 。
private void postForm() { OkHttpClient okHttpClient = new OkHttpClient(); //创建FormBody对象,封装数据(键值对信息) FormBody formBody = new FormBody.Builder() .add("userName", "json") .add("pwd", "123456") .build(); Request request = new Request.Builder() .post(formBody) .url(Host + "/servlet01") .build(); Call call = okHttpClient.newCall(request); //异步执行网络操作 call.enqueue(new Callback() { //请求本身失败时调用 @Override public void onFailure(Call call, IOException e) { showResultOnUiThread("请求为空"); } //请求成功时调用 @Override public void onResponse(Call call, Response response) throws IOException { String result = response.body().string(); showResultOnUiThread(result); } });} 当使用call的异步请求方式时,需要重写两个方法onFailure和onResponse,当请求失败时(连接失败或读写超时)调用onFailure,请求成功时调用onResponse。
可以写一个简单的服务端来验证一下是否可以请求成功:
@WebServlet("/servlet01")public class servlet01 extends HttpServlet { @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.setCharacterEncoding("utf-8"); resp.setCharacterEncoding("utf-8"); String userName = req.getParameter("userName"); String pwd = req.getParameter("pwd"); if(userName == null || "".equals(userName)){ resp.getWriter().write("用户名不能为空"); }else if(pwd == null || "".equals(pwd)){ resp.getWriter().write("密码不能为空"); }else { resp.getWriter().write("欢迎:" + userName); } }} 3.post上传json格式数据
使用Gson需要先添加依赖:
implementation'com.google.code.gson:gson:2.10.1'
当上传json数据时,自然需要用到RequestBody来封装json数据,同时还需用MediaType来设置数据类型(也就是我们想要上传的数据的类型)。
private void postJson() { OkHttpClient okHttpClient = new OkHttpClient(); //1.创建json数据 User user = new User(); user.setUsername("json"); user.setPwd("123456"); String json = new Gson().toJson(user); //2.通过RequestBody封装json数据 RequestBody requestBody = RequestBody.create( MediaType.parse("application/json;charset=utf-8"),//设置数据类型 json//数据 ); Request request = new Request.Builder() .post(requestBody) .url(Host + "/servlet02") .build(); Call call = okHttpClient.newCall(request); try { Response response = call.execute(); String result = response.body().string(); showResultOnUiThread(result); } catch (IOException e) { throw new RuntimeException(e); }} 同样写一个简单服务端来测试一下:
@WebServlet("/servlet02")public class servlet02 extends HttpServlet { @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.setCharacterEncoding("utf-8"); resp.setCharacterEncoding("utf-8"); BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(req.getInputStream())); String data = bufferedReader.readLine(); resp.getWriter().write("json:" + data); }} 4.文件上传
通过OkHttp上传文件的步骤与上传json数据一致,只需更换设置的数据类型即可。因为上传的需要是安卓客户端的数据,所以我们需要先在安卓客户端添加数据。
打开路径data/data/com.example.okhttp/files,在files目录下添加一张图片,之后就可以开始上传了。第一次打开时没有files这个目录,需要手动创建。
同时还需要给app添加访问sd卡的权限,在AndroidManifest.xml中添加:
客户端上传文件:
private void upImg() { //通过文件路径打开文件 String path = getFilesDir().getAbsolutePath() +"/zj.png"; File file = new File(path); OkHttpClient okHttpClient = new OkHttpClient(); RequestBody requestBody = RequestBody.create( MediaType.parse("application/octet-stream"), file ); Request request = new Request.Builder() .post(requestBody) .url(Host + "/servlet02") .build(); Call call = okHttpClient.newCall(request); try { Response response = call.execute(); String result = response.body().string(); showResultOnUiThread(result); } catch (IOException e) { throw new RuntimeException(e); }} 服务端接收文件:
@WebServlet("/servlet02")public class servlet02 extends HttpServlet { @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.setCharacterEncoding("utf-8"); resp.setCharacterEncoding("utf-8"); File file = new File(filePath); ServletInputStream inputStream = req.getInputStream(); FileOutputStream fileOutputStream = new FileOutputStream(file); byte[] bytes = new byte[1024]; int len = -1; while((len = inputStream.read(bytes)) != -1){ fileOutputStream.write(bytes, 0, len); fileOutputStream.flush(); } resp.getWriter().write("上传成功!"); inputStream.close(); fileOutputStream.close(); }} 5.文件下载
下载文件时不需要上传数据,因此不用创建RequestBody对象,只需发送请求即可。
private void downImg() { OkHttpClient okHttpClient = new OkHttpClient(); Request request = new Request.Builder() .url(Host2 + "/servlet03") .build(); Call call = okHttpClient.newCall(request); try { Response response = call.execute(); //获取返回的输入流 InputStream inputStream = response.body().byteStream(); //转成bitmap数据 Bitmap bitmap = BitmapFactory.decodeStream(inputStream); runOnUiThread(new Runnable() { @Override public void run() { img_img.setImageBitmap(bitmap); } }); } catch (IOException e) { throw new RuntimeException(e); }} 服务端提供数据:
@WebServlet("/servlet03")public class servlet03 extends HttpServlet { @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { File file = new File(filePath); ServletOutputStream outputStream = resp.getOutputStream(); BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(outputStream); BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(file)); byte[] bytes = new byte[1024]; int len = -1; while((len = bufferedInputStream.read(bytes)) != -1){ bufferedOutputStream.write(bytes, 0, len); } bufferedOutputStream.close(); bufferedInputStream.close(); }}