Android --- Retrofit 上传/下载文件扩展实现进度的监听
生活随笔
收集整理的這篇文章主要介紹了
Android --- Retrofit 上传/下载文件扩展实现进度的监听
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
本文使用okhttp作為client來做,其實說白了跟用okhttp做下載上傳進度監(jiān)聽幾乎一樣,參考了這篇文章:Android OkHttp文件上傳與下載的進度監(jiān)聽擴展
1. 首先我們寫兩個接口用來下載和上傳的進度監(jiān)聽回調(diào):
/*** 請求體進度回調(diào)接口,用于文件上傳進度回調(diào)*/ public interface ProgressRequestListener {void onRequestProgress(long bytesWritten, long contentLength, boolean done); }/*** 響應(yīng)體進度回調(diào)接口,用于文件下載進度回調(diào)*/ public interface ProgressResponseListener {void onResponseProgress(long bytesRead, long contentLength, boolean done); }2. 實現(xiàn) ProgressRequestBody、ProgressResponseBody
ProgressRequestBody類繼承RequestBody用于請求進度監(jiān)聽,用于文件上傳進度監(jiān)聽:
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; import rx.Observable;/*** 包裝的請求體,處理進度*/ public class ProgressRequestBody extends RequestBody {//實際的待包裝請求體private RequestBody requestBody;//進度回調(diào)接口private ProgressRequestListener progressListener;//包裝完成的BufferedSinkprivate BufferedSink bufferedSink;/*** 構(gòu)造函數(shù),賦值* @param requestBody 待包裝的請求體* @param progressListener 回調(diào)接口*/public ProgressRequestBody(RequestBody requestBody, ProgressRequestListener progressListener) {this.requestBody = requestBody;this.progressListener = progressListener;}/*** 重寫調(diào)用實際的響應(yīng)體的contentType* @return MediaType*/@Overridepublic MediaType contentType() {return requestBody.contentType();}/*** 重寫調(diào)用實際的響應(yīng)體的contentLength* @return contentLength* @throws IOException 異常*/@Overridepublic long contentLength() throws IOException {return requestBody.contentLength();}/*** 重寫進行寫入* @param sink BufferedSink* @throws IOException 異常*/@Overridepublic void writeTo(BufferedSink sink) throws IOException {if (bufferedSink == null) { // //包裝bufferedSink = Okio.buffer(sink(sink));}//寫入requestBody.writeTo(bufferedSink);//必須調(diào)用flush,否則最后一部分?jǐn)?shù)據(jù)可能不會被寫入bufferedSink.flush();}/*** 寫入,回調(diào)進度接口* @param sink Sink* @return Sink*/private Sink sink(Sink sink) {return new ForwardingSink(sink) {//當(dāng)前寫入字節(jié)數(shù)long bytesWritten = 0L;//總字節(jié)長度,避免多次調(diào)用contentLength()方法long contentLength = 0L;@Overridepublic void write(Buffer source, long byteCount) throws IOException {super.write(source, byteCount);if (contentLength == 0) {//獲得contentLength的值,后續(xù)不再調(diào)用contentLength = contentLength();}//增加當(dāng)前寫入的字節(jié)數(shù)bytesWritten += byteCount;//回調(diào)if(progressListener != null){progressListener.onRequestProgress(bytesWritten, contentLength, bytesWritten == contentLength);}}};} }ProgressResponseBody 繼承 ResponseBody 用于下載進度監(jiān)聽:
package com.cm.retrofit.http;/*** Created by Cmad on 2016/4/28.*/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;/*** 包裝的響體,處理進度*/ public class ProgressResponseBody extends ResponseBody {//實際的待包裝響應(yīng)體private final ResponseBody responseBody;//進度回調(diào)接口private final ProgressResponseListener progressListener;//包裝完成的BufferedSourceprivate BufferedSource bufferedSource;/*** 構(gòu)造函數(shù),賦值** @param responseBody 待包裝的響應(yīng)體* @param progressListener 回調(diào)接口*/public ProgressResponseBody(ResponseBody responseBody, ProgressResponseListener progressListener) {this.responseBody = responseBody;this.progressListener = progressListener;}/*** 重寫調(diào)用實際的響應(yīng)體的contentType** @return MediaType*/@Overridepublic MediaType contentType() {return responseBody.contentType();}/*** 重寫調(diào)用實際的響應(yīng)體的contentLength** @return contentLength* @throws IOException 異常*/@Overridepublic long contentLength() {return responseBody.contentLength();}/*** 重寫進行包裝source** @return BufferedSource*/@Overridepublic BufferedSource source() {if (bufferedSource == null) {//包裝bufferedSource = Okio.buffer(source(responseBody.source()));}return bufferedSource;}/*** 讀取,回調(diào)進度接口** @param source Source* @return Source*/private Source source(Source source) {return new ForwardingSource(source) {//當(dāng)前讀取字節(jié)數(shù)long totalBytesRead = 0L;@Overridepublic long read(Buffer sink, long byteCount) throws IOException {long bytesRead = super.read(sink, byteCount);//增加當(dāng)前讀取的字節(jié)數(shù),如果讀取完成了bytesRead會返回-1totalBytesRead += bytesRead != -1 ? bytesRead : 0;//回調(diào),如果contentLength()不知道長度,會返回-1if(progressListener != null){progressListener.onResponseProgress(totalBytesRead, responseBody.contentLength(), bytesRead == -1);}return bytesRead;}};} }上面兩個類里的writeTo跟source方法用到了sink跟Source,這兩個類屬于Okio,也是Square開源的java io補充庫,有興趣的可以去了解一下,這里就不做詳細介紹了.
3. 實現(xiàn)HttpClientHelper類
HttpClientHelper用于創(chuàng)建okhttp client,并對okhttpclient添加攔截事件,將requestBody和responseBody替換成我們自己實現(xiàn)的ProgressRequestBody和ProgressResponseBody
package com.cm.retrofit.http;import java.io.IOException;import okhttp3.Interceptor; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response;/*** Created by Cmad on 2016/4/28.*/ public class HttpClientHelper {/*** 包裝OkHttpClient,用于下載文件的回調(diào)* @param progressListener 進度回調(diào)接口* @return 包裝后的OkHttpClient*/public static OkHttpClient addProgressResponseListener(final ProgressResponseListener progressListener){OkHttpClient.Builder client = new OkHttpClient.Builder();//增加攔截器client.addInterceptor(new Interceptor() {@Overridepublic Response intercept(Chain chain) throws IOException {//攔截Response originalResponse = chain.proceed(chain.request());//包裝響應(yīng)體并返回return originalResponse.newBuilder().body(new ProgressResponseBody(originalResponse.body(), progressListener)).build();}});return client.build();}/*** 包裝OkHttpClient,用于上傳文件的回調(diào)* @param progressListener 進度回調(diào)接口* @return 包裝后的OkHttpClient*/public static OkHttpClient addProgressRequestListener(final ProgressRequestListener progressListener){OkHttpClient.Builder client = new OkHttpClient.Builder();//增加攔截器client.addInterceptor(new Interceptor() {@Overridepublic Response intercept(Chain chain) throws IOException {Request original = chain.request();Request request = original.newBuilder().method(original.method(), new ProgressRequestBody(original.body(),progressListener)).build();return chain.proceed(request);}});return client.build();} }4. 使用
File file = new File(fileUri); RequestBody requestFile =RequestBody.create(MediaType.parse("multipart/form-data"), file); //將requestFile封裝成ProgressRequestBody傳入 MultipartBody.Part body =MultipartBody.Part.createFormData("file", file.getName(), new ProgressRequestBody(requestFile,this));//this是在當(dāng)前類實現(xiàn)了ProgressRequestListener接口 Call<ResponseBody> call = service.upload(body);service 需要自己封裝
總結(jié)
以上是生活随笔為你收集整理的Android --- Retrofit 上传/下载文件扩展实现进度的监听的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mysql - 要问 varchar 能
- 下一篇: Android --- 漂亮的 Load