OkHttp 使用详情二
来源:互联网 发布:手机版设计软件 编辑:程序博客网 时间:2024/06/05 16:39
一概要:
OkHttp,作为当下最流行的网络请求方式,是非常方便且高效的。但是如果现在有个需求,上传和
下载文件并且在过程中给用户提供友好的界面提示(提示用户下载的进度)。似乎没方法用简单的
OkHttp API来实现。网上搜索了一个下,找到一个一些方法。在证明确实可行之后。在此归纳总结
出这篇博客。
(OkHttp的基本使用,请参考:OkHttp 使用详情一)
二实现
1,文件的下载进度监听
# 编写ProgressResponseListener接口,定义回调方法onResponseProgress(longbytesRead,longcontentLength,booleandone)
# 编写ProgressResponseBody继承ResponseBody,并且在source方法中实时的回调接口的回调方法。
# 为OkHttpClient添加拦截器Interceptor,在拦截器中将原本ResponseBody封装成自定义的ProgressResponseBody。
自定义接口ProgresResponseListener
/** * 响应进度回调接口,用于文件下载 * Created by SongbinWang on 2017/7/6. */public interface ProgressResponseListener { void onResponseProgress(long bytesRead, long contentLength, boolean done);}封装ResponseBody
package com.wang.csdnapp.okhttp;import android.support.annotation.Nullable;import com.wang.csdnapp.util.LogUtil;import java.io.IOException;import okhttp3.MediaType;import okhttp3.ResponseBody;import okio.Buffer;import okio.BufferedSource;import okio.ForwardingSource;import okio.Okio;import okio.Source;/** * Created by SongbinWang on 2017/7/6. */public class ProgressResponseBody extends ResponseBody{ private static final String TAG = "ProgressResponseBody"; //待包装的响应 private ResponseBody responseBody; private ProgressResponseListener responseListener; private BufferedSource bufferedSource; public ProgressResponseBody(ResponseBody responseBody, ProgressResponseListener responseListener){ this.responseBody = responseBody; this.responseListener = responseListener; } @Override public MediaType contentType() { return responseBody.contentType(); } @Override public long contentLength() { return responseBody.contentLength(); } @Override public BufferedSource source() { if(bufferedSource == null){ //包装 bufferedSource = Okio.buffer(source(responseBody.source())); } return bufferedSource; } private Source source(Source source){ return new ForwardingSource(source) { long totalByteRead = 0l; @Override public long read(Buffer sink, long byteCount) throws IOException { long byteRead = super.read(sink, byteCount); //增加当前读取的字节,如果读取完成,byteRead = -1 totalByteRead += (byteRead == -1 ? 0 : byteRead); //回调,如果responseBody.contentLength 不知道 返回-1 LogUtil.i(TAG, "totalByteRead:" + totalByteRead + ",byteRead:" + byteRead + ",contentLength:" + responseBody.contentLength()); responseListener.onResponseProgress(totalByteRead, responseBody.contentLength(), byteRead == -1); return byteRead; } }; }}添加拦截器
/** * 包装OkHttpClient用于下载文件 * @param responseListener * @return */ public static OkHttpClient addProgressResponseListener( final ProgressResponseListener responseListener){ OkHttpClient okHttpClient = new OkHttpClient.Builder() .connectTimeout(30, TimeUnit.SECONDS) .readTimeout(60*60, TimeUnit.SECONDS) .writeTimeout(60*60, TimeUnit.SECONDS) //添加拦截器 .addInterceptor(new Interceptor() { @Override public Response intercept(Chain chain) throws IOException { //拦截 Response originalResponse = chain.proceed(chain.request()); //包装响应体并返回 return originalResponse.newBuilder() .body(new ProgressResponseBody(originalResponse.body(), responseListener)) .build(); } }) .build(); return okHttpClient; }2,文件上传进度监听
# 编写接口ProgressRequestListener,并定义回调方法onRequestProgress(long bytesWritten, long contentLength, boolean done);
# 编写ProgressRequestBody继承RequestBody,并在sink方法中实时调用接口ProgressRequestListener的回调方法。
# 将RequestBody替换成ProgressRequestBody。
自定义接口ProgressRequestListener:
/** * 请求进度回调接口,用于文件上传 * Created by SongbinWang on 2017/7/6. */public interface ProgressRequestListener { void onRequestProgress(long bytesWritten, long contentLength, boolean done);}自定义封装RequestBody
package com.wang.csdnapp.okhttp;import java.io.IOException;import okhttp3.MediaType;import okhttp3.RequestBody;import okio.Buffer;import okio.BufferedSink;import okio.ForwardingSink;import okio.Okio;import okio.Sink;/** * Created by SongbinWang on 2017/7/6. */public class ProgressRequestBody extends RequestBody{ private RequestBody requestBody; private ProgressRequestListener requestListener; private BufferedSink bufferedSink; public ProgressRequestBody(RequestBody requestBody, ProgressRequestListener requestListener) { this.requestBody = requestBody; this.requestListener = requestListener; } @Override public MediaType contentType() { return requestBody.contentType(); } @Override public long contentLength() throws IOException { return requestBody.contentLength(); } @Override public void writeTo(BufferedSink sink) throws IOException { if(bufferedSink == null){ //包装 bufferedSink = Okio.buffer(sink(sink)); } //写入 requestBody.writeTo(bufferedSink); //必须调用flush 否侧最后一部分,不会写入 bufferedSink.flush(); } /** * 写入包装,回调进度接口 * @param sink * @return */ private Sink sink(Sink sink){ return new ForwardingSink(sink){ //当前写入的总字节数 private long totalWrite = 0l; //整个文件的总大小 private long contentLength = 0l; @Override public void write(Buffer source, long byteCount) throws IOException { super.write(source, byteCount); if(contentLength == 0){ //获得之后,不再调用 contentLength = requestBody.contentLength(); } //增加总写入的字节数 totalWrite += byteCount; //回调 requestListener.onRequestProgress(totalWrite, contentLength, totalWrite == contentLength); } }; }}
三使用
首先文件上传非常的简单,只要不RequestBody替换成我们封装好了的ProgressRequestBody(带
ProgressRequestListener)。
下面是下载的使用验证(编写一个DownloadService,启动Service就会执行下载操作):
import android.app.Service;import android.content.Intent;import android.os.IBinder;import com.wang.csdnapp.okhttp.ProgressHelper;import com.wang.csdnapp.okhttp.ProgressResponseListener;import com.wang.csdnapp.util.LogUtil;import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.util.concurrent.TimeUnit;import okhttp3.OkHttpClient;import okhttp3.Request;import okhttp3.Response;/** * Created by SongbinWang on 2017/7/6. */public class DownloadService extends Service implements ProgressResponseListener{ private static final String TAG = "DownloadService"; //工作线程中执行耗时的网络请求 Thread thread = null; private OkHttpClient okHttpClient = ProgressHelper.addProgressResponseListener(this);//添加了拦截器 @Override public int onStartCommand(Intent intent, int flags, int startId) { LogUtil.i(TAG, "onStartCommand current Thread:" + Thread.currentThread()); thread = new Thread(){ @Override public void run() { //要下载的文件,这里是一张图片 String url = "http://g.hiphotos.baidu.com/zhidao/pic/item/18d8bc3eb13533fa746b1558aed3fd1f40345be3.jpg"; LogUtil.i(TAG, "url:" + url); Request request = new Request.Builder().url(url).build(); InputStream in = null; FileOutputStream fos = null; try { String path = "mnt/sdcard/Download/qq.jpg";//下载的后文件的路径和名称 File file = new File(path); LogUtil.i(TAG, "loacal path:" + file.getAbsolutePath()); Response response = okHttpClient.newCall(request).execute();//同步执行 if(response.isSuccessful()){ LogUtil.i(TAG, "response successfull!"); in = response.body().byteStream(); fos = new FileOutputStream(file); int len = -1; byte[] buf = new byte[1024]; while((len = in.read(buf)) != -1){ fos.write(buf, 0, len); } }else{ LogUtil.i(TAG, "response failiure:" + response); } } catch (IOException e) { e.printStackTrace(); }finally {//关闭流对象 if(in != null){ try{ in.close();}catch (Exception e){}} if(fos != null){ try{ fos.close();}catch (Exception e){}} } } }; thread.start(); return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { super.onDestroy(); } @Override public IBinder onBind(Intent intent) { return null; } //文件下载进度的回调 @Override public void onResponseProgress(long bytesRead, long contentLength, boolean done) { LogUtil.i(TAG, "onResponseProgress currentThread: " + Thread.currentThread() ); LogUtil.i(TAG, "onResponseProgress byteRead:" + bytesRead + ",contentLength:" + contentLength + ",done" + done); }}注意onResponseProgress的回调是在工作线程中执行的,不能直接更新UI。
参考:http://blog.csdn.net/sbsujjbcy/article/details/48194701
阅读全文
0 0
- OkHttp 使用详情二
- OkHttp使用详情
- OkHttp 使用详情一
- xListView+OKHttp使用(二)
- OKhttp,MVP,RecyclerView,联合使用,点击条目进入详情页
- OKHttp通信使用(二)
- Android OKHttp介绍与使用(二)
- 使用OkHttp的那些事儿(二)
- 流程中心使用详情(二)表单控件
- log4J配置详情 二
- OKHttp使用
- OkHttp 使用
- OKHttp 使用
- okhttp使用
- OKHTTP使用
- Okhttp使用
- Okhttp使用
- Okhttp使用
- 对于“大数据”的15条干货思考分享
- Googel 浏览器 模拟发送请求工具--Advanced REST Client
- Linux环境下Eclipse编程小技巧
- VBA中Activate方法和Select方法的区别
- vba常用函数
- OkHttp 使用详情二
- JSON语法及使用
- 03——BootStrap之CRUD(静态页面)
- jQuery code
- 葵花宝典 十六 jsp与servlet技术 注释
- opencv安装及初用总结
- groovy安装
- 欢迎使用CSDN-markdown编辑器
- REQUIRED与REQUIRED_NEW