简介

okhttp是一个第三方类库,用于android中请求网络。这是一个开源项目,是安卓端最火热的轻量级框架,由移动支付Square公司贡献(该公司还贡献了Picasso和LeakCanary) 。用于替代HttpUrlConnection和Apache HttpClient(android API23 里已移除HttpClient)。

依赖

implementation 'com.squareup.okhttp3:okhttp:4.4.0'

同步请求方式(get请求)

步骤一  创建请求接口网址

我使用了http://www.sosoapi.com/ 来创建了一个访问接口,用来验证OkHttp是否请求成功。如果你有兴趣了解,可以直接进入网站,里面有详细的demo演示。后续我将不在赘述这段。

我在请求响应里添加了一段JSON数据:

[
{
"name": "get测试",
"content": "你成功获取了数据"
}
]

步骤二  创建JSON解析方法

这里我写一下解析JSON数据的方法,来解析get或者post得到的JSON数据。后续我将不在赘述这段。

/**
* JSON 解析方法
* @param jsonData
* @return
*/
public String readJSONContent(String jsonData){
try {
StringBuffer sb = new StringBuffer();
JSONArray jsonArray = new JSONArray(jsonData);
for (int i=0;i<jsonArray.length();i++){
JSONObject jsonObject = jsonArray.getJSONObject(i);
sb.append(jsonObject.getString("name")+"\n");
sb.append(jsonObject.getString("content")+"\n");
}
return sb.toString();
} catch (JSONException e) {
Log.e("JSONException错误", "readContent: "+e.toString());
return e.toString();
}
}

步骤三  创建OkHttp 同步请求

/**
* 同步请求
*/
public void synchro(){
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
OkHttpClient okHttpClient = new OkHttpClient();//创建单例
Request request = new Request.Builder()//创建请求
.url("http://www.sosoapi.com/pass/mock/12003/test/gettest")
.build();
try {
Response response = okHttpClient.newCall(request).execute();//执行请求
mContent = response.body().string();//得到返回响应,注意response.body().string() 只能调用一次! runOnUiThread(new Runnable() {
@Override
public void run() {
mtextView.setText(readJSONContent(mContent));
}
});
} catch (IOException e) {
e.printStackTrace();
Log.e("OkHttpActivity", e.toString() );
}
}
});
thread.start();
}

注意!response.body().string() 只能调用一次! 因为响应主体 RessponseBody 持有的资源可能会很大,所以 OkHttp 并不会将其直接保存到内存中,只是持有数据流连接。只有当我们需要时,才会从服务器获取数据并返回。同时,考虑到应用重复读取数据的可能性很小,所以将其设计为一次性流(one-shot),读取后即 '关闭并释放资源'

效果图:

异步请求方式(get请求)

注意1:异步请求方式,请求的回调会在子线程里,所以如果需要更新UI你需要切换到主线程。且你不需要在new 一个线程包裹这个异步请求了。另外如何切换到主线程请使用 Handler 例子:

注意2:在异步请求方法里,请不要将 public void onResponse(Call call, final Response response)回调里的response回调数据放到UI线程里解析,因为有一个天坑,有可能在UI线程里解析的时候response里面却还没有塞入数据(我也觉得很神奇,不知道写okhttp的公司是怎么想的,为什么不处理完所有数据在提供回调)

private Handler mHandler = new Handler(Looper.getMainLooper());
            mHandler.post(new Runnable() {
@Override
public void run() {
//主线程 }
});

创建异步请求

     /**
* get异步请求
*/
public void asynchronous(){
OkHttpClient okHttpClient = new OkHttpClient();
Request request = new Request.Builder()
.url("http://www.sosoapi.com/pass/mock/12003/test/gettest")
.build();
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
//失败回调 } @Override
public void onResponse(Call call, final Response response) throws IOException {
            mContent = readJSONContent(response.body().string());//注意response.body().string() 只能调用一次!
//响应成功,这个回调在子线程中,所以不需要创建线程
if (response.isSuccessful()){
//isSuccessful方法:如果代码位于(200…300)中,则返回true,这意味着请求已成功接收
runOnUiThread(new Runnable() {
@Override
public void run() {
try {
//因为在子线程,所以我们需要回到主线程中更新UI数据
mtextView.setText(mContent);
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
}
});
}

Post请求

post请求也同时有同步与异步方法,与上面一致,所以这里就不展示了,下面我们来看看post请求发送

/**
* post请求
*/
public void post(){
new Thread(new Runnable() {
@Override
public void run() {
//实例
OkHttpClient okHttpClient = new OkHttpClient(); //创建post请求数据表单
RequestBody requestBody = new FormBody.Builder()
.add("name","请求post")
.add("password","123456")
.build();
//创建请求
final Request request = new Request.Builder()
.url("http://www.sosoapi.com/pass/mock/12003/test/posttest")
.post(requestBody)//添加post请求
.build(); try {
//发送请求得到响应
final Response response = okHttpClient.newCall(request).execute();
runOnUiThread(new Runnable() {
@Override
public void run() {
try {
mtextView.setText(readJSONContent(response.body().string()));//注意response.body().string() 只能调用一次!
} catch (IOException e) {
e.printStackTrace();
}
}
});
} catch (IOException e) {
e.printStackTrace();
} }
}).start(); }

效果图:

取消网络请求

取消okhttp的网络请求很简单只需要

call.cancel();

如何鉴别是网络异常还是主动取消,请求取消的回调在onFailure(Call call, IOException e)里回调,这个时候我们需要再次判断onFailure里回调的是我们自己主动取消的还是网络异常报错的

mCall.enqueue(new Callback() {//发送请求
@Override
public void onFailure(final Call call, final IOException e) {
if (call.isCanceled()){
listener.onCancel(); }else {
listener.onFailure(call, e);
}
}
//省略下面代码...

RequestBody创建

RequestBody是okhttp  post发送数据配置类.在这之前我们先了解下回顾一下body类型

http有四种body类型,Content-Type POST提交数据的方式:
  • application/x-www-form-urlencoded 表单数据
  • multipart/form-data 表单文件上传
  • application/json 序列化JSON数据
  • text/xml XML数据

这些body类型需要在http header头部就写上,但是okhttp不需要我们手动在header写上类型了.okhttp提供了FormBody和MultipartBody的类型,方便你的快速创建application/x-www-form-urlencoded 与 multipart/form-data

FormBody 创建方式

/**
* 此body是 默认application/x-www-form-urlencoded,你可以进入FormBody类查看,第一行静态常量就是这个
*/
public void FormBody(){
FormBody.Builder builder = new FormBody.Builder();
builder.add("key","content");
builder.build();
}

MultipartBody 创建方式

/**
* multipart/form-data
*/
public void MultipartBody(){
RequestBody requestBody = new RequestBody() {
@Override
public MediaType contentType() {
return null;
} @Override
public void writeTo(BufferedSink sink) throws IOException {
//上传流 sink.write() }
};
MultipartBody.Builder builder = new MultipartBody.Builder();
builder.addFormDataPart("key","content");//表单数据
builder.addFormDataPart("file_key","/path/image.jpg",requestBody);//文件数据
MultipartBody multipartBody = builder.build();
}

手动创建4种body

当然,有特殊需求你还可以添加手动其他body类型,create也支持好几种数据的上传形式

 /**
* 手动创建4种body
*/
public void RequestBody(){
RequestBody applicationFormUrlencodedBody = RequestBody.create(MediaType.parse("application/x-www-form-urlencoded; charset=utf-8"),new String("demo").getBytes());
RequestBody multipartBody = RequestBody.create(MediaType.parse("multipart/form-data; charset=utf-8"),new File("/path/image.jpg"));
RequestBody jsonBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"),"content");
RequestBody textbody = RequestBody.create(MediaType.parse("text/xml; charset=utf-8"),"content"); }

实现OkHttpClient客户端单例模式

public class OkHttpClientCreate {
private static final boolean IS_RETRY = false;//失败是否重连
private static final int CONNECT_TIME = 10;//设置连接超时时间 单位:秒
private static final int READ_TIME = 10;//设置读取超时时间
private static final int WRITE_TIME = 10;//设置写入超时间
private static OkHttpClient mOkHttpClient;
public static OkHttpClient CreateClient(){
if (mOkHttpClient == null){
return mOkHttpClient = new OkHttpClient.Builder()
.retryOnConnectionFailure(IS_RETRY)
.connectTimeout(CONNECT_TIME,TimeUnit.SECONDS)//连接超时
.readTimeout(READ_TIME,TimeUnit.SECONDS)//读取超时
.writeTimeout(WRITE_TIME,TimeUnit.SECONDS)//写入超时
// .callTimeout()//呼叫超时,设置此参数为整体流程请求的超时时间
// .addInterceptor() //设置拦截器
// .authenticator() //设置认证器
// .proxy()//设置代理
.build();
}
return mOkHttpClient;
} public static void destroy(){
mOkHttpClient = null;
} }

Android 开发 框架系列 OkHttp使用详解的更多相关文章

  1. Android 开发 框架系列 OkHttp拦截器

    前言 此篇博客只讲解okhttp的拦截器功能的详细使用,如果你还不太了解okhttp可以参考我另外一篇博客 Android 开发 框架系列 OkHttp使用详解 添加Interceptor的简单例子 ...

  2. Android 开发 框架系列 OkHttp文件上传功能实现(含断点续传)

    前言 此篇博客只是上传功能的记录demo,如果你还不太了解okhttp可以参考我的另一篇博客https://www.cnblogs.com/guanxinjing/p/9708575.html 代码部 ...

  3. Android 开发 框架系列 OkHttp文件下载功能实现(含断点续传)

    前言 此篇博客只是下载功能的记录demo,如果你还不太了解okhttp可以参考我的另一篇博客https://www.cnblogs.com/guanxinjing/p/9708575.html 代码部 ...

  4. Android开发:文本控件详解——TextView(一)基本属性

    一.简单实例: 新建的Android项目初始自带的Hello World!其实就是一个TextView. 在activity_main.xml中可以新建TextView,从左侧组件里拖拽到右侧预览界面 ...

  5. Android开发:文本控件详解——TextView(二)文字跑马灯效果实现

    一.需要使用的属性: 1.android:ellipsize 作用:若文字过长,控制该控件如何显示. 对于同样的文字“Android开发:文本控件详解——TextView(二)文字跑马灯效果实现”,不 ...

  6. Android 网络框架之Retrofit2使用详解及从源码中解析原理

    就目前来说Retrofit2使用的已相当的广泛,那么我们先来了解下两个问题: 1 . 什么是Retrofit? Retrofit是针对于Android/Java的.基于okHttp的.一种轻量级且安全 ...

  7. Android开发数据存储之ContentProvider详解

    转载:十二.ContentProvider和Uri详解 一.使用ContentProvider(内容提供者)共享数据 ContentProvider在android中的作用是对外共享数据,也就是说你可 ...

  8. Android 开发 框架系列 Google的ORM框架 Room

    目录 简介 导入工程 使用流程概况 一个简单的小Demo 深入学习 @Entity使用 自定义表名 tableName  自定义字段名@ColumnInfo 主键 @PrimaryKey 索引 @In ...

  9. 转: Android开发中的MVP架构详解(附加链接比较不错)

    转: http://www.codeceo.com/article/android-mvp-artch.html 最近越来越多的人开始谈论架构.我周围的同事和工程师也是如此.尽管我还不是特别深入理解M ...

随机推荐

  1. 201671010142 <java程序设计>初次学习心得与感悟

    从开始对JDK的配置就遇到了问题,从这点就可以知道自己知识的薄弱.又知道了在控制台下一些常用命令的掌握.对知识的理解挺艰难,比如遇到一个新的问题就不知道该从哪里入手,有时候还不知道到底问题是啥.接受能 ...

  2. 黄金点游戏 结队i项目

    结对编程——黄金点游戏   本次的结对编程的项目是黄金点游戏,我的结对对象是冯雨倩,我们的编程能力都不太好,而且都对C语言更熟悉些,因此我们决定用C语言来实现. (1)分工:角色分配:冯雨倩是领航员, ...

  3. Java容器解析系列(5) AbstractSequentialList LinkedList 详解

    AbstractSequentialList为顺序访问的list提供了一个骨架实现,使实现顺序访问的list变得简单; 我们来看源码: /** AbstractSequentialList 继承自 A ...

  4. oracle高级分组

    基本group by用法 create table test_table(a varchar(20),b varchar(20),c varchar(20)) insert into test_tab ...

  5. python -django 之第三方支付

    神魔是第三方支付: 第三方支付是指具有一定实力和信誉保障的第三方独立机构.通过与各大银行签订合同,建立连接用户和银行支付结算系统的平台,从而实现电子支付模式.从另一个角度来看,第三方支付就是非金融机构 ...

  6. spring jpa Pageable 分页之---多条件排序

    Sort sort = new Sort(Direction.ASC, "sort").and(new Sort(Direction.DESC, groupField));//排序 ...

  7. 《Linux内核原理与分析》第二周作业

    反汇编一个简单的C程序 1.实验要求 使用: gcc –S –o test.s test.c -m32 命令编译成汇编代码,对汇编代码进行分析总结.其中test.c的具体内容如下: int g(int ...

  8. Java面试题 Web+EJB & Spring+数据结构& 算法&计算机基础

    六.Web 部分:(共题:基础40 道,基础37 道,中等难度3 道) 122.说出Servlet 的生命周期,并说出Servlet 和CGI 的区别? [基础] 答:Web 容器加载Servlet ...

  9. Java_集合面试题

    Java_集合面试题 0.链表,队列和栈的区别? 链表是一种存储结构,指得是存储时候除了要存储数据元素之外,还要用数据元素一起的另外空间存储数据元素的关系. 队列和栈都是线性表,属于逻辑结构范畴,都是 ...

  10. Window离线环境下如何安装pyhanlp

    Hanlp在离线环境下的安装我是没有尝试过的,分享SunJW_2017的这篇文章就是关于如何在离线环境下安装hanlp的.我们可以一起来学习一下! HanLP是一款优秀的中文自然语言处理工具,可以实现 ...