你必须学会的okhttp——入门篇
2016-12-03 14:27
477 查看
早在毕业那段期间,群里有很多小伙伴在问关于okhttp的问题,当时因为不了解。所以没有回答的上。记得十月份有次面试,一个面试官问我关于网络请求的东西时,我记得当时我是说。我是通过HttpClient封装了一个网络请求的工具类。当然,或许他想问的是我关于okhttp有没有了解把。谷歌在6.0中删除了关于httpclient的API。(其实我有httpclient源码)。于是乎,为了了解下,最近还是学习了下。
高效的使用http,使应用运行更快,更省流量
响应缓存数据,避免重复网络请求
无缝的支持GZIP从而来减少流量的使用
使用简单方便,请求和响应的APi具有流畅的建造和不变性。同时支持同步异步调用回调函数
如果网络出现问题,他会从常见的连接问题中恢复
如果服务器配置多个URL,当第一个连接失败时,它会尝试链接下一个
OKio
2) Request:构建请求参数,如url,请求方式,请求参数,header等。
3) Call:生成一个具体请求实例,相当于将请求封装成了任务;两种方式:
4) Response:结果响应
此时,基本的get与post就这么介绍完了。那么用到网络请求除了get和post还有什么呢?对了,就是文件的上传与下载。针对群里一些小伙伴需要得到当前的进度,所以下面会上整体的代码,我会在放完代码后做出解释。
此时你们会看到我判断了onProgressStateListener此接口不为空的情况,其实就是如果不需要得到当前的进度,我们就无需实现此接口。如果不需要得到进度,你也可以把上面createProgressRequestBody方法换成这句话:
这里我们需要把inputstream写入sd卡:
这里也和上传是一样的,你需要得到进度的时候实现此接口。
简单说下学习okhttp的理由
google在Android 6.0中删除了关于Httpclient的APi,采用的则是okhttp高效的使用http,使应用运行更快,更省流量
响应缓存数据,避免重复网络请求
无缝的支持GZIP从而来减少流量的使用
使用简单方便,请求和响应的APi具有流畅的建造和不变性。同时支持同步异步调用回调函数
如果网络出现问题,他会从常见的连接问题中恢复
如果服务器配置多个URL,当第一个连接失败时,它会尝试链接下一个
配置环境
github地址:http://github.com/square/okhttp在build.gradle添加:
compile 'com.squareup.okhttp:okhttp:2.7.5' compile 'com.squareup.okio:okio:1.11.0'
jar下载地址:
OkhttpOKio
基本使用教程
1) OkHttpClient:新建一个OkHttpClient实例,用于处理请求。2) Request:构建请求参数,如url,请求方式,请求参数,header等。
3) Call:生成一个具体请求实例,相当于将请求封装成了任务;两种方式:
①、call.execute(),非异步方式,会阻塞线程,等待返回结果。 ②、call.enqueue(Callback),异步方式。
4) Response:结果响应
HttpGet
同步http请求
private OkHttpClient okHttpClient = new OkHttpClient(); private Response response; okHttpClient.setConnectTimeout(15, TimeUnit.SECONDS); okHttpClient.setReadTimeout(15, TimeUnit.SECONDS); okHttpClient.setWriteTimeout(15, TimeUnit.SECONDS); Request request = new Request.Builder().url(url).get().build(); try { response = okHttpClient.newCall(request).execute(); if (response.isSuccessful()) { Log.i(TAG, " onResponse() reuslt=" + response.body().string()); } } catch (IOException e) { e.printStackTrace(); } }
异步http请求
private OkHttpClient okHttpClient = new OkHttpClient(); private Response response; okHttpClient.setConnectTimeout(15, TimeUnit.SECONDS); okHttpClient.setReadTimeout(15, TimeUnit.SECONDS); okHttpClient.setWriteTimeout(15, TimeUnit.SECONDS); Request request = new Request.Builder().url(url).get().build(); okHttpClient.newCall(request).enqueue(new Callback() { public void onFailure(Call call, IOException e) { Log.e(TAG, "onFailure() e=" + e); } public void onResponse(Call call, final Response response) throws IOException { Log.i(TAG, " onResponse() reuslt=" + response.body().string()); } });
HttpPost
看了上面的简单的get请求,基本上整个的用法也就掌握了。post和get的用法差不多。同步的Post请求
okHttpClient.setConnectTimeout(15, TimeUnit.SECONDS); okHttpClient.setReadTimeout(15, TimeUnit.SECONDS); okHttpClient.setWriteTimeout(15, TimeUnit.SECONDS); RequestBody body=new FormEncodingBuilder().add("name","马云飞").build(); Request request = new Request.Builder().url(url).post(body).build(); try { response = okHttpClient.newCall(request).execute(); if (response.isSuccessful()) { Log.i(TAG, " onResponse() reuslt=" + response.body().string()); } } catch (IOException e) { e.printStackTrace(); } }
异步的Post请求
okHttpClient.setConnectTimeout(15, TimeUnit.SECONDS); okHttpClient.setReadTimeout(15, TimeUnit.SECONDS); okHttpClient.setWriteTimeout(15, TimeUnit.SECONDS); RequestBody body=new FormEncodingBuilder().add("name","马云飞").build(); Request request = new Request.Builder().url(url).post(body).build(); okHttpClient.newCall(request).enqueue(new Callback() { public void onFailure(Call call, IOException e) { Log.e(TAG, "onFailure() e=" + e); } public void onResponse(Call call, final Response response) throws IOException { Log.i(TAG, " onResponse() reuslt=" + response.body().string()); } });
此时,基本的get与post就这么介绍完了。那么用到网络请求除了get和post还有什么呢?对了,就是文件的上传与下载。针对群里一些小伙伴需要得到当前的进度,所以下面会上整体的代码,我会在放完代码后做出解释。
文件上传
public String uploadFile(String uploadUrl, File file) { if (httpUtils.isConnnected()) { RequestBody filebody = createProgressRequestBody(MEDIA_OBJECT_STREAM, file); RequestBody body = new MultipartBuilder().type(MultipartBuilder.FORM).addFormDataPart(file.getName(), file.getName(), filebody).build(); Request request = new Request.Builder() .url(uploadUrl) .post(body) .build(); Response response = null; try { response = okHttpClient.newCall(request).execute(); return response.body().string(); } catch (IOException e) { } } return null; }
public RequestBody createProgressRequestBody(final MediaType contentType, final File file) { return new RequestBody() { public MediaType contentType() { return contentType; } public long contentLength() { return file.length(); } public void writeTo(BufferedSink sink) throws IOException { Source source; try { source = Okio.source(file); Buffer buf = new Buffer(); long total = contentLength(); long current = 0; for (long readCount; (readCount = source.read(buf, 2048)) != -1; ) { sink.write(buf, readCount); current += readCount; if (onProgressStateListener != null) { onProgressStateListener.upload(byteUtils.getSize(current), byteUtils.getSize(total), byteUtils.getByte(current), byteUtils.getByte(total)); } } } catch (Exception e) { e.printStackTrace(); } } }; }
此时你们会看到我判断了onProgressStateListener此接口不为空的情况,其实就是如果不需要得到当前的进度,我们就无需实现此接口。如果不需要得到进度,你也可以把上面createProgressRequestBody方法换成这句话:
filebody=RequestBody.create(MEDIA_OBJECT_STREAM,file);
文件下载
Request request = new Request.Builder().url(httpDownloadBean.getUrl()).build(); okHttpClient.newCall(request).enqueue(new Callback() { public void onResponse(Response response) { InputStream inputStream = null; try { download_total = response.body().contentLength(); inputStream = response.body().byteStream(); if (response.isSuccessful()) { writeSDFromInput(httpDownloadBean.getStoragepath(), httpDownloadBean.getFilepath(), inputStream); } else { } } catch (IOException e) { e.printStackTrace(); } } public void onFailure(Request arg0, IOException arg1) { } });
这里我们需要把inputstream写入sd卡:
public File writeSDFromInput(String path, String fileName, InputStream input) { File file = null; OutputStream output = null; try { fileSupport.createSDDir(path); file = fileSupport.createSDFile(path + fileName); output = new FileOutputStream(file); byte buffer[] = new byte[1024]; int length = 0; long current = 0; while ((length = input.read(buffer)) != -1) { current += length; if (onProgressStateListener != null) { onProgressStateListener.download(byteUtils.getSize(current), byteUtils.getSize(download_total), byteUtils.getByte(current), byteUtils.getByte(download_total)); } output.write(buffer, 0, length); } output.flush(); } catch (Exception e) { e.printStackTrace(); } finally { try { output.close(); } catch (Exception e) { e.printStackTrace(); } } return file; }
这里也和上传是一样的,你需要得到进度的时候实现此接口。
总结
Okhttp默认的配置为我们提供了非常重要实用功能。通过采用上述步骤,你可以增加它的灵活性和内省的能力并提高应用程序的质量。我对比过我用Httpclient和Okhttp的写的工具类,如果不需要得到进度的话,代码量差了一倍之多。从此而知,okhttp的确很好用。相关文章推荐
- EchoServer设计到实现(六)
- HTTP Header中的ETag
- http以post方式上传一个文件,构造其请求头和消息报文
- http发post请求 返回错误500a
- Nginx配置HTTPS和HTTP
- 简析TCP的三次握手与四次分手
- 【树莓派】树莓派移动网络连接(配置4G网卡)
- HTTPS那些事(二)SSL证书
- Android安全使用HTTPS
- android中检测网络是否断开
- 关于nginx的ngx_http_image_filter_module裁剪图片后方向改变的解决方案
- Linux网络安全模型及iptables详解(1)
- HTTP详解(1)-工作原理
- 理解socket、tcp、udp、http
- Android网络编程(十一)源码解析Retrofit
- CDN网络的原理
- 【C#】使用TcpListener和TcpClient实现简单通信
- Go语言TCP/UDP Socket编程
- 常见的HTTP状态码
- 【Window】获取电脑连接的网络信息