重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
这篇文章主要介绍Okhttp、Retrofit进度怎么获取,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!
成都创新互联公司是专业的开化网站建设公司,开化接单;提供成都网站设计、成都网站建设、外贸网站建设,网页设计,网站设计,建网站,PHP网站建设等专业做网站服务;采用PHP框架,可快速的进行开化网站开发网页制作和功能扩展;专业做搜索引擎喜爱的网站,专业的做网站团队,希望更多企业前来合作!
起因
对于广大Android开发者来说,最近用的最多的网络库,莫过于Okhttp啦(Retrofit依赖Okhttp)。
Okhttp不像SDK内置的HttpUrlConnection一样,可以明确的获取数据读写的过程,我们需要执行一些操作。
介绍
Retrofit依赖Okhttp、Okhttp依赖于Okio。那么Okio又是什么鬼?别急,看官方介绍:
Okio is a library that complements java.io and java.nio to make it much easier to access, store, and process your data.
翻译过来就是,Okio是一个实现了java.io和java.nio的一个类库,它让连接,存储,处理你的数据更加轻松~(Okio既是读写相关类库,获取进度要从Okio入手)。
好吧,对于广大开发者来说,内心是这样的:TM又要看你文档和用例,按你规则走,轻松个毛啊!
其实,读下API,看下Example熟悉后,人家设计的还是很棒哒。
废话不多说,先看效果。
效果
实际代码:
//添加下载拦截器(this参数是实现下载进度接口的对象) mDownClient = new OkHttpClient.Builder() //只需要一行代码就行了 .addNetworkInterceptor(new DownloadInterceptor(this)) .build(); //添加上传拦截器(this参数是实现上传回调接口的对象) mUploadClient = new OkHttpClient.Builder() //只需要一行代码就行了 .addNetworkInterceptor(new UploadInterceptor(this)) .build();
你只需要一行代码是不行的!我为什么行?因为这是我写的封装类库啊~(最后放地址)
思路
Okhttp依赖Okio进行了数据的读写动作,我们需要找到Okio进行处理。那么,如何加上呢?
Okhttp可以添加Interceptor(拦截器),我们可以通过拦截器的接口方法,获取对应的responseBody、requestBody对象进行操作。然后我们就获取了读写相关的实现方法。具体实现是通过Source、Sink对象。
Source官方解释:Supplies a stream of bytes. Use this interface to read data from wherever it's located。
Sink官方解释:Receives a stream of bytes. Use this interface to write data wherever it's needed。
一句话概括:Source对象是对输入流的包装(下载读数据),Sink是对输出流的包装(写数据上传)。
实现
根据需要添加下载、上传Interceptor
//添加下载拦截器(this参数是实现下载进度接口的对象) mDownClient = new OkHttpClient.Builder() .addNetworkInterceptor(new DownloadInterceptor(this)) .build(); //添加上传拦截器(this参数是实现上传回调接口的对象) mUploadClient = new OkHttpClient.Builder() .addNetworkInterceptor(new UploadInterceptor(this)) .build();
拦截器具体实现
//下载拦截器 public class DownloadInterceptor implements Interceptor { private OnDownloadListener mListener; public DownloadInterceptor( OnDownloadListener listener) { mListener = listener; } @Override public Response intercept(Chain chain) throws IOException { //封装ressponse对象 Response response = wrapResponse(chain.proceed(chain.request())); return response; } private Response wrapResponse(Response response) { if (response == null || response.body() == null) { return response; } //获取处理后的response对象 Response wrapResponse = getWrapResponse(response); return wrapResponse; } private Response getWrapResponse(Response response) { ProgressInfo info = new ProgressInfo(); info.setTime(System.currentTimeMillis()+""); info.setUrl(response.request().url().toString()); Response.Builder builder = response.newBuilder(); //封装responseBody,传入相关参数,获取进度数据回调 return builder.body(new WrapResponseBody(response.body(),info,mListener)).build(); } } --------------------------------------分割--------------------------------------- //上传拦截器 public class UploadInterceptor implements Interceptor { private OnUploadListener mListener; public UploadInterceptor(OnUploadListener listener) { mListener = listener; } @Override public Response intercept(Chain chain) throws IOException { //封装request对象 Request request = wrapRequest(chain.request()); Response response = chain.proceed(request); return response; } private Request wrapRequest(Request request) { if (request == null || request.body() == null) { return request; } Request.Builder builder = request.newBuilder(); ProgressInfo info = new ProgressInfo(); HttpUrl url = request.url(); info.setUrl(url.toString()); info.setTime(System.currentTimeMillis()+""); //封装requestBody,传入参数,获取数据进度回调 builder.method(request.method(),new WrapRequestBody(request.body(),info,mListener)); return builder.build(); } } responseBody、requestBody相关实现 //继承ResponseBody实现具体方法 public class WrapResponseBody extends ResponseBody { private Handler mHandler = new Handler(Looper.getMainLooper()); private ResponseBody mResponseBody; private OnDownloadListener mListener; private ProgressInfo mInfo; private BufferedSource mBufferedSource; private boolean mDoProgress; //传入进度,以及监听对象 public WrapResponseBody(ResponseBody responseBody, ProgressInfo info, OnDownloadListener listener) { mResponseBody = responseBody; mInfo = info; mListener = listener; } @Nullable @Override public MediaType contentType() { //接口方法,返回类型 return mResponseBody.contentType(); } @Override public long contentLength() { long contentLength = mResponseBody.contentLength(); //gzip压缩格式会返回-1,目前处理是在请求头信息指定("Accept-Encoding","identity")表示不压缩 if (contentLength == -1) { mDoProgress = false; mHandler.post(new Runnable() { @Override public void run() { //切换线程,进行失败回调 mListener.onDownLoadGetContentLengthFail(mInfo); } }); } else { mDoProgress = true; } return contentLength; } @Override public BufferedSource source() { //WrapSource(继承ForwardingSource,ForwardingSource实现了Source接口) if (mBufferedSource == null) { mInfo.setContentLength(contentLength()); //传入参数,读取具体进度信息,并回调 WrapSource wrapSource = new WrapSource(mResponseBody.source(), mInfo, mListener,mDoProgress); mBufferedSource = Okio.buffer(wrapSource); } return mBufferedSource; } } --------------------------------------分割--------------------------------------- //继承ResquestBody实现具体方法 public class WrapRequestBody extends RequestBody { private RequestBody mRequestBody; private OnUploadListener mListener; private ProgressInfo mInfo; private boolean mDoProgress; private Handler mHandler = new Handler(Looper.getMainLooper()); //传入进度,以及监听对象 public WrapRequestBody(RequestBody requestBody, ProgressInfo info, OnUploadListener listener) { mRequestBody = requestBody; mListener = listener; mInfo = info; } @Override public MediaType contentType() { //接口方法,返回类型 return mRequestBody.contentType(); } @Override public long contentLength() throws IOException { try { //上传内容长度,有异常走failWrok处理 long l = mRequestBody.contentLength(); mDoProgress = true; return l; } catch (IOException e) { e.printStackTrace(); failWork(); return -1; } } //进行失败处理 private void failWork() { mDoProgress = false; mHandler.post(new Runnable() { @Override public void run() { //切换线程,回调失败信息 mListener.onUploadGetContentLengthFail(mInfo); } }); } @Override public void writeTo(BufferedSink sink) throws IOException { mInfo.setContentLength(contentLength()); // WrapSink (继承ForwardingSink,ForwardingSink实现了Sink接口) ///传入参数,读取具体进度信息,并回调 WrapSink wrapSink = new WrapSink(sink, mInfo, mListener, mDoProgress); BufferedSink buffer = Okio.buffer(wrapSink); mRequestBody.writeTo(buffer); buffer.flush(); } } WrapSource、WrapSink相关实现 //继承ForwardingSource 实现具体方法 public class WrapSource extends ForwardingSource { private Handler mHandler = new Handler(Looper.getMainLooper()); private Source mSource; private ProgressInfo mInfo; private OnDownloadListener mListener; private boolean mDoProgress; public WrapSource(Source source, ProgressInfo info, OnDownloadListener listener, boolean doProgress) { //传入源Source、进度信息、监听进度等信息。 super(source); mSource = source; mInfo = info; mListener = listener; //传入是否继续执行回调boolean参数,如果之前执行有异常,则不再继续执行回调 mDoProgress = doProgress; } @Override public long read(Buffer sink, long byteCount) throws IOException { //获取具体进度信息,来到了熟悉的具体IO long read = super.read(sink, byteCount); if (read != -1) { long l = mInfo.getCurrentLength() + read; mInfo.setCurrentLength(l); mHandler.post(new Runnable() { @Override public void run() { if (mDoProgress) { //切换到主线程,回调数据 mListener.onDownLoadProgress(mInfo); } } }); } return read; } } --------------------------------------分割--------------------------------------- //继承ForwardingSink 实现具体方法 public class WrapSink extends ForwardingSink { private Handler mHandler = new Handler(Looper.getMainLooper()); public OnUploadListener mListener; public ProgressInfo mInfo; public boolean mDoProgress; public WrapSink(Sink delegate, ProgressInfo info, OnUploadListener listener, boolean doProgress) { //传入源Source、进度信息、监听进度等信息。 super(delegate); mInfo = info; mListener = listener; //传入是否继续执行回调boolean参数,如果之前执行有异常,则不再继续执行回调 mDoProgress = doProgress; } @Override public void write(Buffer source, long byteCount) throws IOException { super.write(source, byteCount); //获取具体进度信息,来到了熟悉的具体IO long l = mInfo.getCurrentLength() + byteCount; mInfo.setCurrentLength(l); mHandler.post(new Runnable() { @Override public void run() { if (mDoProgress) { //切换到主线程,回调数据 mListener.onUpLoadProgress(mInfo); } } }); } }
以上是“Okhttp、Retrofit进度怎么获取”这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注创新互联行业资讯频道!