OKHttp 数据读写进度监听分析

来源:互联网 发布:淘宝店自己可以开吗 编辑:程序博客网 时间:2024/06/07 22:15


请尊重原创,转载请注明出处 http://blog.csdn.net/mabeijianxi/article/details/77992315


大致架构图



(窃图地址: https://blog.piasy.com/2016/07/11/Understand-OkHttp/,可以先详细看看)


写入进度监听(比如上传)

可以对 RequestBody 进行装饰, writeTo() 中 对 Sink 再进行装饰,可以直接利用 ForwardingSink ,重写其 write(), 其内即可获得每次写入的字节数,RequestBody具体装饰如下:

public class CountingRequestBody extends RequestBody{    protected RequestBody delegate;    protected Listener listener;    protected CountingSink countingSink;    public CountingRequestBody(RequestBody delegate, Listener listener)    {        this.delegate = delegate;        this.listener = listener;    }    @Override    public MediaType contentType()    {        return delegate.contentType();    }    @Override    public long contentLength()    {        try        {            return delegate.contentLength();        } catch (IOException e)        {            e.printStackTrace();        }        return -1;    }    @Override    public void writeTo(BufferedSink sink) throws IOException    {        countingSink = new CountingSink(sink);        BufferedSink bufferedSink = Okio.buffer(countingSink);        delegate.writeTo(bufferedSink);        bufferedSink.flush();    }    protected final class CountingSink extends ForwardingSink    {        private long bytesWritten = 0;        public CountingSink(Sink delegate)        {            super(delegate);        }        @Override        public void write(Buffer source, long byteCount) throws IOException        {            super.write(source, byteCount);            bytesWritten += byteCount;            listener.onRequestProgress(bytesWritten, contentLength());        }    }    public static interface Listener    {        public void onRequestProgress(long bytesWritten, long contentLength);    }}

返回数据的进度监听(比如下载):

可以在这个责任链中添加一个 NetWorkInterceptor ,对返回的 ResponseBody 进行包装,在 source() 函数中对 Source 再进行一个包装,可以直接利用 ForwdingSource ,重写其 read() 函数即可,ResponseBody 具体包装如下:

private static class OkHttpProgressResponseBody extends ResponseBody {        private final HttpUrl url;        private final ResponseBody responseBody;        private final ResponseProgressListener progressListener;        private BufferedSource bufferedSource;        OkHttpProgressResponseBody(HttpUrl url, ResponseBody responseBody,                                   ResponseProgressListener progressListener) {            this.url = url;            this.responseBody = responseBody;            this.progressListener = progressListener;        }        @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 totalBytesRead = 0L;                @Override                public long read(Buffer sink, long byteCount) throws IOException {                    long bytesRead = super.read(sink, byteCount);                    long fullLength = responseBody.contentLength();                    if (bytesRead == -1) { // this source is exhausted                        totalBytesRead = fullLength;                    } else {                        totalBytesRead += bytesRead;                    }                    progressListener.update(url, totalBytesRead, fullLength);                    return bytesRead;                }            };        }    }

然后就是需要的时候添加一个 NetWorkInterceptor即可,如下:

 OkHttpClient client = new OkHttpClient.Builder()            .addNetworkInterceptor(new Interceptor() {                @Override                public Response intercept(Chain chain) throws IOException {                    Request request = chain.request();                    Response response = chain.proceed(request);                    return response.newBuilder()                            .body(new OkHttpProgressResponseBody(request.url(), response.body(),                                    progressListener))                            .build();                }            }).build();

progressListener 接口自己定义一个即可。

总结

通过添加 Interceptor 的方式可以简洁对请求数据或者响应数据进行装饰。

阅读全文
1 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 托朋友代购给了钱联系不上人怎么办 签了合同被加盟商骗了怎么办 百度云盘下载时本地空间不足怎么办 百度云盘隐私空间没密码忘了怎么办 华为云空间的帐号密码忘记了怎么办 快递被快递公司弄丢了怎么办 快递到了人不在那个地方了怎么办 微信被骗了1千多怎么办 客户货已经用啦要求退款退货怎么办 网购收到别人退货的东西怎么办 好省输入订单编号查不到订单怎么办 快递没有当面验收后发现损坏怎么办 支付宝电脑付款风控异常怎么办 京东买东西地址填错了怎么办 商场卖的衣服跟官网差价大怎么办 网购的衣服有好几个破洞怎么办 出租发票有牌号是假的怎么办 支付宝里的多收多保被降级了怎么办 超市购物卡余额与实际不符怎么办 发广告的公众号无法取消关注怎么办 扣扣需要手机验证码登录怎么办 驾校报了联系不了教练了怎么办 手机号被别人注册了百度网盘怎么办 注册公司云证书申请成功后怎么办 淘宝购物卖家迟迟不发货怎么办 淘宝直播顾客加购物车不下单怎么办 东方航空联程机票航班延误怎么办 别别人伸请更换手机绑定qq怎么办 绑定手机号的扣扣忘记密码怎么办 微信公众号个人主体变更公司怎么办 微信号注册成订阅号了怎么办 微信开通了企鹅影院会员怎么办 注销公众号对公账号填写错误怎么办 国外邮的东西在北京扣了手续怎么办 微信购物商城买的东西不发货怎么办 魅族手机电话图标没有了怎么办 新商盟网页新商盟网页打不开怎么办 京东商城购物车装满了怎么办 商家想入住美团没有营业执照怎么办 旅行团定好的人数临时加人该怎么办 淘宝上发货后12天未收到款怎么办