okhttp教程——起步篇
okhttp教程——起步篇
这篇文章主要总结Android著名网络框架-okhttp
的基础使用,后续可能会有关于他的高级使用。
okhttp是什么
okhttp
是Android端的一个Http客户端,其基础功能相当于Android自带的HttpURLConnection
和Apache HTTP Client
,但他却比自带的2个Http客户端优越很多,一者是写法简单,二者okhttp处理很多网络复杂问题,如会从很多常用的连接问题中自动恢复。如果您的服务器配置了多个IP地址,当第一个IP连接失败的时候,OkHttp会自动尝试下一个IP。OkHttp还处理了代理服务器问题和SSL握手失败等等很多问题。关于第二者,这篇文章不讨论。
okhttp的导入
Gradle导入
compile 'com.squareup.okhttp3:okhttp:3.2.0'compile 'com.squareup.okio:okio:1.6.0'
okhttp基础使用
这里我们主要介绍简单的使用,介绍内容如下
- get请求
- post请求,参数是键值对
- post请求,多种类型的body
- 文件下载
- 加入Gson
get请求
get请求分为同步get和异步get,两者的区别主要get的方式是工作在另一个线程还是工作在本线程。请求的方式大同小异。
首先定义一个OkHttpClient对象,如下
private OkHttpClient client = new OkHttpClient();
然后构建一个Request,构建方式如下:
Request request = new Request.Builder().
url("http://www.baidu.com").
build();
这个是最简单的request的构建方式,当然我们可以构建的很复杂。
Request request = new Request.Builder().url("http://www.baidu.com").addHeader("User-Agent","android").header("Content-Type","text/html; charset=utf-8").build();
通过addHeader和header方法为请求增加请求头部,注意使用header(name, value)可以设置唯一的name、value。如果已经有值,旧的将被移除,然后添加新的。使用addHeader(name, value)可以添加多值(添加,不移除已有的)。
同步的get方法,通过client.newCall(request).execute()方法得到请求的response.
Response response = okHttpClient.newCall(request).execute();
OkHttp封装了很多处理response的方法,比如response.headers()的得到headers.
Headers headers = response.headers();for (int i = 0; i < headers.size(); i++) {
System.out.println(headers.name(i) + ": " + headers.value(i)); }
结果如下:
Date: Mon, 18 Apr 2016 05:23:43 GMT
Content-Type: text/html; charset=utf-8
Transfer-Encoding: chunked
Connection: Keep-Alive
Vary: Accept-Encoding
Set-Cookie: BAIDUID=A323EC9BF678C0EB78E20741FD71211B:FG=1; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com
Set-Cookie: BIDUPSID=A323EC9BF678C0EB78E20741FD71211B; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com
Set-Cookie: PSTM=1460957023; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com
Set-Cookie: BDSVRTM=0; path=/
Set-Cookie: BD_HOME=0; path=/
Set-Cookie: H_PS_PSSID=1434_19672_18281_19690_17948_18205_19558_15952_12257; path=/; domain=.baidu.com
P3P: CP=" OTI DSP COR IVA OUR IND COM "
Cache-Control: private
Cxy_all: baidu+2db7793e0e32b9f6c20be8f623e1ae43
Expires: Mon, 18 Apr 2016 05:22:55 GMT
X-Powered-By: HPHP
Server: BWS/1.1
X-UA-Compatible: IE=Edge,chrome=1
BDPAGETYPE: 1
BDQID: 0xfacc6fc10004ca96
BDUSERID: 0
OkHttp-Sent-Millis: 1460957021226
OkHttp-Received-Millis: 1460957021430
响应报文的实体可以通过response.body().string()获取;如果希望获得返回的二进制字节数组,则调用response.body().bytes();如果你想拿到返回的inputStream,则调用response.body().byteStream()。
异步的get请求得到的response方法是通过如下方法
okHttpClient.newCall(request).enqueue(new Callback() {@Overridepublic void onFailure(Call call, IOException e) {} @Overridepublic void onResponse(Call call, Response response) throws IOException {}});
在onResponse方法中,执行请求成功的代码,onFailure方法中,执行请求失败的代码,下面给一个完整的异步get的栗子
import android.os.Bundle;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.text.method.ScrollingMovementMethod;
import android.widget.TextView;import java.io.IOException;import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Headers;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;public class MainActivity extends AppCompatActivity {private OkHttpClient okHttpClient = new OkHttpClient();public TextView show;public Handler handler = new Handler();@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);show = (TextView) findViewById(R.id.show);show.setMovementMethod(ScrollingMovementMethod.getInstance());Request request = new Request.Builder().url("http://www.baidu.com").addHeader("User-Agent", "android").header("Content-Type", "text/html; charset=utf-8").get().build();okHttpClient.newCall(request).enqueue(new Callback() {@Overridepublic void onFailure(Call call, IOException e) {}@Overridepublic void onResponse(Call call, final Response response) throws IOException {final Headers headers = response.headers();final String str = response.body().string();handler.post(new Runnable() {@Overridepublic void run() {for (int i = 0; i < headers.size(); i++) {show.append(headers.name(i) + ": " + headers.value(i));show.append(str);}}});}});}}
其实按照官网说的,回调是发生在response 的headers准备好就发生的,所以有时候请求response的实体部分会发生阻塞。
post请求——键值对为参数。
post请求和get请求除了在构建request上面不同以外,在处理response上面都是一样的,所以下面我们只讨论一下post构建request,当然post也是支持同步post和异步post的,可以参考get方法。
在构建post的request时候,首先用FormBody.Builder去构建request的body部分,栗子如下,当然这是OKHttp3的方法.
FormBody.Builder builder = new FormBody.Builder();for(int i = 0 ; i < key.size() ;i ++){builder.add(key.get(i),value.get(i));}RequestBody body = builder.build();
builder中add的是要加入的参数键值对。得到要构造的body后用
Request request = new Request.Builder().url(url).post(body).build();
获得请求的request,后面的操作就和get方法是一样的,这里可以参考异步get的栗子,构建一个post的request.下面的写法原封不变。
post请求--多种类型的body
上文已经说了post和get的用法主要在构建不同的request上面,所以接下来我们主要讨论的也是如何构建request.
参考上面,我们首先要创建一个requestBody,我们可以用下面的方式去构建,当然这也是okhttp3的方法
MultipartBody.Builder builder = new MultipartBody.Builder().setType(MultipartBody.FORM);
已表单上传的形式去提交post。我们看一下builder的方法
/** Add a part to the body. */public Builder addPart(RequestBody body) {return addPart(Part.create(body));}/** Add a part to the body. */public Builder addPart(Headers headers, RequestBody body) {return addPart(Part.create(headers, body));}/** Add a form data part to the body. */public Builder addFormDataPart(String name, String value) {return addPart(Part.createFormData(name, value));}/** Add a form data part to the body. */public Builder addFormDataPart(String name, String filename, RequestBody body) {return addPart(Part.createFormData(name, filename, body));}
从这里我们可以看出可以直接用 public Builder addFormDataPart(String name, String filename, RequestBody body)
上传一个File,最后一个参数是请求的实体,可以通过 RequestBody.create(final MediaType contentType, final File file)
获得,而MediaType
则可以通过下面方法获得
//调用judgeType方法
private static final MediaType MEDIA_TYPE = MediaType.parse(judgeType(fileName);
//judge方法如下
private String judgeType(String path) {FileNameMap fileNameMap = URLConnection.getFileNameMap();String contentTypeFor = fileNameMap.getContentTypeFor(path);if (contentTypeFor == null) {contentTypeFor = "application/octet-stream";}return contentTypeFor;}
由于我后台能力比较渣,这里用一个官网的例子来实现一遍我刚才讨论的方法。
MultipartBody.Builder builder = new MultipartBody.Builder().setType(MultipartBody.FORM).addFormDataPart("image", "logo-square.png",RequestBody.create(MEDIA_TYPE_PNG, new File("website/static/logo-square.png")));
RequestBody requestBody = builder.build();Request request = new Request.Builder().header("Authorization", "Client-ID " +"9199fdef135c122").url("https://api.imgur.com/3/image").post(requestBody).build();
当然除了这个方法以外,调用如下方法也是可以的,我们可以利用name和filename自己构造Header传上去。
public Builder addPart(Headers headers, RequestBody body) {return addPart(Part.create(headers, body))
栗子如下:
builder.addPart(Headers.of("Content-Disposition", "form-data; name=\"" + name + "\"; filename=\"" + fileName + "\""),fileBody);
后面的写法和上面类似,这样我们就实现了文件上传的写法。
文件下载
刚才我们上面已经说了,希望获得返回的二进制字节数组,则调用response.body().bytes();如果你想拿到返回的inputStream,则调用response.body().byteStream()。换句话说,文件的下载可以简单的通过get请求,得到相应的response,在把他的实体转换成二进制流写入文件,就是实现了文件的下载。主要的写法就是文件的读写,跟OKHttp关系不大,当然我们也可以用okio来实现文件的读写,这里水平有限就不介绍了。下面给一个简单的例子。
private void _download(final String url, final String destFileDir, final ResultCallback callback) {final Request request = new Request.Builder().url(url).build();final Call call = okHttpClient.newCall(request);call.enqueue(new Callback() {@Overridepublic void onFailure(Call call, IOException e) {}@Overridepublic void onResponse(Call call, Response response) throws IOException {InputStream is = null;byte[] buf = new byte[2048];int len = 0;FileOutputStream fos = null;try {is = response.body().byteStream();File file = new File(destFileDir, getFileName(url));fos = new FileOutputStream(file);while((len = is.read(buf)) != -1){fos.write(buf,0,len);}fos.flush();//....省略后续对已经保存的文件的操作} catch (IOException e) {e.printStackTrace();}finally {try {if (is != null) is.close();} catch (IOException e) {}try{if (fos != null) fos.close();} catch (IOException e){}}}});}
加入Gson
接下来,我们讨论一个很实际的问题,Android的网络请求一般不会去请求一个网站的Html,更多的是请求后台接口的Json文件,所以我们用Gson来处理json的解析。这一部分和前面就不同了,前面多数讲的是如何构建不同的request来得到response,而对响应的结果,处理都是一致的。但这里主要的写法就是用Gson去处理response,而request的构建则根据上面介绍的方法去构建,无需改变。
Gson的导入
compile 'com.google.code.gson:gson:2.6.2'
比如我们后台给出的api是这样一个json文件
{"status": 0,"intro": "你好","shopName": "byhieg", "message": "查询成功",
}
则我们可以简单的构建这样的一个Test.java文件,如下所示:
public class Test {/*** status : 0* intro : byhieg* shopName : byhige* message : 查询成功*/private int status;private String intro;private String shopName;private String message;public int getStatus() {return status;}public void setStatus(int status) {this.status = status;}public String getIntro() {return intro;}public void setIntro(String intro) {this.intro = intro;}public String getShopName() {return shopName;}public void setShopName(String shopName) {this.shopName = shopName;}public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}
}
在获得到response之后,用如下代码把Json文件解析成result对象。然后调用result对象的get方法就可以得到json文件中的intro的值和shopname的值,以及status和message.这里就不多介绍了
Test result = new Gson().fromJson(response.body().string,Test.class);
总结
简单介绍了okHttp的使用,对于一些高级用法请关注下篇文章,本人水平有限,如有错误,还望指正。
转载于:https://www.cnblogs.com/qifengshi/p/5405550.html
okhttp教程——起步篇相关推荐
- python 小甲鱼小游戏_Python 小甲鱼教程 Easygui 篇
Python 小甲鱼教程 Easygui 篇 终于有点实质性可以看到摸到的界面了,搜了一下虽然easygui用的不多,但是作为一个起步,z,----,先了解一下吧,e,毕竟道理想通. 下面按照小甲鱼的 ...
- Floodlight 入门 之 起步篇 - 如何处理PacketIN消息
Floodlight 入门 之 起步篇 - 如何处理PacketIN消息 2017-3-2 小论文写不出来好纠结,今天还在做Floodlight开发,好烦躁.这边博文介绍如何处理PacketIN消息, ...
- Floodlight 入门 之 起步篇 - 建立一个Floodlight模块
Floodlight 入门 之 起步篇 - 建立一个Floodlight模块 2017-3-1 网上也有不少关于Floodlight的入门教程了,我写该博文的目的主要是问了整理个人在学习和使用Floo ...
- .Net魔法堂:史上最全的ActiveX开发教程——发布篇
一. 前言 接着上一篇<.Net魔法堂:史上最全的ActiveX开发教程--开发篇>,本篇讲述如何发布我们的ActiveX. 二.废话少讲,马上看步骤! 1. 打包 C#开发的Activ ...
- SpringCloud 教程 | 第二篇: 服务消费者(rest+ribbon)
转载请标明出处: blog.csdn.net/forezp/arti- 本文出自方志朋的博客 在上一篇文章,讲了服务的注册和发现.在服务架构中,业务都会被拆分成一个独立的服务,服务与服务的通讯是基于h ...
- python语言自学教程-3D图示Python标准自学教程入门篇
内容简介: Python入门篇教程从最基础的计算机发展史.Python的来源与发展历史开始讲起: 依次讲解python变量与表达式.数据类型.运算符.流程控制语句等,末尾通过课堂练习.课后作业以及微型 ...
- 【helloworld】-微信小程序开发教程-入门篇【1】
1. 开篇导言 本节目标:旨在演示如何用开发者工具构建并运行简单的 helloworld 应用. 目标用户:无编程经验,但对微信小程序感兴趣的同学. 学习目标:开发者工具的基本使用流程,即创建.导入. ...
- linux usb3.0改2.0,TX1入门教程硬件篇-切换USB2.0与USB3.0
TX1入门教程硬件篇-切换USB2.0与USB3.0 说明: 介绍如何切换TX1USB口的为2.0或3.0版本 步骤: 编辑extlinux.conf文件,修改usb_port_owner_info= ...
- 微信公众号开发入门教程第一篇
微信公众号开发入门教程第一篇 关键字:微信公众平台开发 作者:方倍工作室 在这篇微信公众平台开发教程中,我们假定你已经有了PHP语言程序.MySQL数据库.计算机网络通讯.及HTTP/XML/CSS/ ...
最新文章
- atm c语言流程图_c语言ATM机程序
- OpenGL绘制一个三角形的实例
- 京东宣布收购拇指阅读,具体金额未披露
- url模糊匹配优化_详情页怎么做SEO优化?
- django源码简析——后台程序入口
- matlab简单分析矩阵乘法——一阶行向量乘一阶列向量
- 【转】在C#中读写INI配置文件
- CM108AH和DP108/DP108T的区别
- 为什么要使用kafka消息队列
- 自研·学术·文献查找
- 计算方法/数值分析牛顿下山法C/C++实现方法
- 锁相环(PLL)基本结构及相关基本知识
- 解决win10开机内存过高的办法(亲测有效)
- uni-app使用iconfont
- android 带刻度的滑动条_Android自定义控件尺子 滚动刻度尺
- atlas 阿里 android,AtlasDemo
- MediaPlayer
- Quectel BC28-CNV 多频段、高性能、低功耗 LTE Cat NB2 无线通信模块[移远通信]
- 前端工程化 | 工程化技术基础
- mac如何定时执行任务
热门文章
- 关于annotation object的旋转
- 火牛单片机rtc时钟配置_怎么用STM32F103RTC进行时钟的配置
- 用scikit-learn和pandas实现线性回归
- php连接mysql执行sql语句_php+mysql 连接服务器、数据库以及执行SQL语句的类库
- html验证用户名长度,JQuery表单字符串长度验证
- git ssh配置完后拉取代码_二、windows下使用git拉取github上的项目(通过设置ssh key方式)...
- qt获取cpu使用率_又一次生产 CPU 高负载排查实践
- React学习笔记三 脚手架生成的index.js内容简介
- python导入自定义函数_python怎么导入自定义函数
- MySQL 5.7.18忘记密码和密码过期解决