1 、引入

Gradle 引入依赖

implementation 'com.squareup.okhttp3:okhttp:3.14.7'
implementation 'com.squareup.okio:okio:1.17.5'

2、 Manifest 申请网络权限

 <uses-permission android:name="android.permission.INTERNET" /><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

3、基本用法

  1. 第一步: 构建OKHttpClient对象
  2. 第二步:构建Request请求对象
  3. 第三步:生成CALL对象
  4. 第四步:call 发起网络请求(同步/异步)

3.1 GET 同步请求

//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() {@Overridepublic void run() {try {Response response = call.execute();} catch (IOException e){e.printStackTrace();}}}).start();

3.2  GET 异步请求

如果要主线程中直接使用,不单独新建子线程,可以用异步请求.

 //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() {@Overridepublic void onFailure(@NotNull Call call, @NotNull IOException e) {}@Overridepublic 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线程。

3.3 同步POST请求

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() {@Overridepublic 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请求。

3.4 POST异步请求

//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() {@Overridepublic void onFailure(@NotNull Call call, @NotNull IOException e) {}@Overridepublic void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {Log.e(TAG, "okhttp POST execute" + response.body().string());}});

3.5 异步上传文件

 //1.构建okHttpClient对象OkHttpClient okHttpClient = new OkHttpClient();//2.构建RequestBody对象//2.1 文件类型MediaType contentType = MediaType.parse("text/x-markdown;charset=utf-8");//2.2 文件内容 stringString 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() {@Overridepublic void onFailure(@NotNull Call call, @NotNull IOException e) {}@Overridepublic 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:<p>xiaoomi</p>

具体的文件上传示例

首先在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() {@Overridepublic void onFailure(@NotNull Call call, @NotNull IOException e) {}@Overridepublic 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请求提交复杂类型的请求体.复杂请求体可以同时包含多种类型的请求数据.

3.6 异步上传Multiparty 文件

  //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() {@Overridepublic void onFailure(@NotNull Call call, @NotNull IOException e) {}@Overridepublic void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {Log.e(TAG, "okhttp POST execute" + response.body().string());}});

在构建RequestBody的时候,使用的MultipartyBody构建的MultipartBody实例,前两个上传的是键值对,第三个上传的是表单.addformDatapart方法的第一个参数是key,第二个是上传文件的名子,第三个参数是需要上传的文件。

3.7 请求配置项

问题:

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@Overridepublic 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) 设置此次请求只能使用网络,不能用缓存.

3.8 取消请求

使用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() {@Overridepublic void run() {call.cancel();}},10,TimeUnit.MICROSECONDS);}call.enqueue(new Callback() {@Overridepublic void onFailure(@NotNull Call call, @NotNull IOException e) {}@Overridepublic 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的基本使用

OKHTTP深入浅出(二)----基本用法相关推荐

  1. VTK:二次方用法实战

    VTK:二次方用法实战 程序输出 程序完整源代码 程序输出 程序完整源代码 #include <vtkActor.h> #include <vtkDataSetMapper.h> ...

  2. Vista Media Center 开发之深入浅出 (二) --Vista Media Center 程序的新建及部署

    原文: http://www.cnblogs.com/wangmiao/articles/1306292.html Vista Media Center 开发之深入浅出 (二) ----- Vista ...

  3. OkHttp(二)—— 拦截器

    本篇文章我们将介绍 OkHttp 的拦截器,拦截器是 OkHttp 的核心,正是因为 OkHttp 内置的五大拦截器各司其职,才使得使用者可以轻松的发送网络请求并收到响应.这五大拦截器分别是: 重定向 ...

  4. 02-Unity深入浅出(二)

    一. Unity声明周期 Unity容器为我们提供了6种生命周期,便于我们根据项目需求来选择使用. (1). 瞬时.默认省略即为瞬时,无论单线程还是多线程,每次都重新创建对象.new Transien ...

  5. [Android 插件化(二)] DroidPlugin 用法

    1 简介 关于Android插件化可以查看我的前一篇博客:  [Android 插件化(一)] DynamicLoadApk的用法 本篇介绍第二种实现插件化的框架,360公司出品的DroidPlugi ...

  6. sqlalchemy(二)高级用法

    本文将介绍sqlalchemy的高级用法. 外键以及relationship 首先创建数据库,在这里一个user对应多个address,因此需要在address上增加user_id这个外键(一对多). ...

  7. Android SQLite (二) 基本用法

    在Android开发中SQLite起着很重要的作用,网上SQLite的教程有很多很多,不过那些教程大多数都讲得不是很全面.本人总结了一些SQLite的常用的方法,借着论坛的大赛,跟大家分享分享的. 一 ...

  8. RxJava+Retrofit+OkHttp深入浅出-终极封装四(多文件下载之断点续传)

    http://blog.csdn.net/wzgiceman/article/details/52911503 转载于:https://www.cnblogs.com/zhangminghan/p/6 ...

  9. 【iOS开发】Alamofire框架的使用二 高级用法

    Alamofire是在URLSession和URL加载系统的基础上写的.所以,为了更好地学习这个框架,建议先熟悉下列几个底层网络协议栈: URL Loading System Programming ...

  10. RabbitMQ延迟消息:死信队列 | 延迟插件 | 二合一用法+踩坑手记+最佳使用心得

最新文章

  1. pythonprint end_python print end =''
  2. 【Python】Python入门-字符串初相识
  3. java证书的安装_Java 第三方证书安装
  4. 学完Java基础后的总结
  5. poj 1160 Post Office(DP简单题)
  6. ArcGIS制图(一)之流向图
  7. 贵州大学计算机科学与技术学院排名,贵州大学的计算机专业全国排名第几?
  8. 【随笔】TongWeb 常见报错
  9. python过滤敏感词汇_Python过滤敏感词汇
  10. 【数字图像处理】直方图规定化(含实现代码)
  11. 【题解】SCOI-2010-连续攻击游戏
  12. 【转载】用reshacker轻松修改系统OEM信息
  13. 我看QQ与360之争
  14. seafile私有云盘搭建全过程记录
  15. 三星j7出现android,三星J7配置曝光 配骁龙625/运行安卓7.0
  16. 如何给生成的exe加图标
  17. 计算机c盘中用户文件夹内的文件改名,Win10-更改c盘下的用户文件夹名
  18. 青柠起始页样式书写+清新风格登录界面——Html+Css+JavaScript
  19. 杰理之通话回音【篇】
  20. CRB开发-总体简介

热门文章

  1. Java 正则表达式匹配规则
  2. 百度文库复制文字(一个按钮,关闭JS功能即可,浏览器100%有效)2021年
  3. 计算机网络中特有符号,计算机基础知识测试题-一肖中特免费公开资料.doc
  4. 百度云盘不限速的方法
  5. Android自定义popWindow教程
  6. lammps不规则界面建模技巧
  7. 安装SQL Server2012
  8. 【白帽子讲Web安全】第一章 我的安全世界观
  9. 基于单片机的交通灯控制系统设计
  10. SQL Server 2008 修改安装路径