日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android --- Retrofit 上传/下载文件扩展实现进度的监听

發布時間:2025/3/21 Android 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android --- Retrofit 上传/下载文件扩展实现进度的监听 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本文使用okhttp作為client來做,其實說白了跟用okhttp做下載上傳進度監聽幾乎一樣,參考了這篇文章:Android OkHttp文件上傳與下載的進度監聽擴展

1. 首先我們寫兩個接口用來下載和上傳的進度監聽回調:

/*** 請求體進度回調接口,用于文件上傳進度回調*/ public interface ProgressRequestListener {void onRequestProgress(long bytesWritten, long contentLength, boolean done); }/*** 響應體進度回調接口,用于文件下載進度回調*/ public interface ProgressResponseListener {void onResponseProgress(long bytesRead, long contentLength, boolean done); }

2. 實現 ProgressRequestBody、ProgressResponseBody

ProgressRequestBody類繼承RequestBody用于請求進度監聽,用于文件上傳進度監聽:

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;//進度回調接口private ProgressRequestListener progressListener;//包裝完成的BufferedSinkprivate BufferedSink bufferedSink;/*** 構造函數,賦值* @param requestBody 待包裝的請求體* @param progressListener 回調接口*/public ProgressRequestBody(RequestBody requestBody, ProgressRequestListener progressListener) {this.requestBody = requestBody;this.progressListener = progressListener;}/*** 重寫調用實際的響應體的contentType* @return MediaType*/@Overridepublic MediaType contentType() {return requestBody.contentType();}/*** 重寫調用實際的響應體的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);//必須調用flush,否則最后一部分數據可能不會被寫入bufferedSink.flush();}/*** 寫入,回調進度接口* @param sink Sink* @return Sink*/private Sink sink(Sink sink) {return new ForwardingSink(sink) {//當前寫入字節數long bytesWritten = 0L;//總字節長度,避免多次調用contentLength()方法long contentLength = 0L;@Overridepublic void write(Buffer source, long byteCount) throws IOException {super.write(source, byteCount);if (contentLength == 0) {//獲得contentLength的值,后續不再調用contentLength = contentLength();}//增加當前寫入的字節數bytesWritten += byteCount;//回調if(progressListener != null){progressListener.onRequestProgress(bytesWritten, contentLength, bytesWritten == contentLength);}}};} }

ProgressResponseBody 繼承 ResponseBody 用于下載進度監聽:

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 {//實際的待包裝響應體private final ResponseBody responseBody;//進度回調接口private final ProgressResponseListener progressListener;//包裝完成的BufferedSourceprivate BufferedSource bufferedSource;/*** 構造函數,賦值** @param responseBody 待包裝的響應體* @param progressListener 回調接口*/public ProgressResponseBody(ResponseBody responseBody, ProgressResponseListener progressListener) {this.responseBody = responseBody;this.progressListener = progressListener;}/*** 重寫調用實際的響應體的contentType** @return MediaType*/@Overridepublic MediaType contentType() {return responseBody.contentType();}/*** 重寫調用實際的響應體的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;}/*** 讀取,回調進度接口** @param source Source* @return Source*/private Source source(Source source) {return new ForwardingSource(source) {//當前讀取字節數long totalBytesRead = 0L;@Overridepublic long read(Buffer sink, long byteCount) throws IOException {long bytesRead = super.read(sink, byteCount);//增加當前讀取的字節數,如果讀取完成了bytesRead會返回-1totalBytesRead += bytesRead != -1 ? bytesRead : 0;//回調,如果contentLength()不知道長度,會返回-1if(progressListener != null){progressListener.onResponseProgress(totalBytesRead, responseBody.contentLength(), bytesRead == -1);}return bytesRead;}};} }

上面兩個類里的writeTo跟source方法用到了sink跟Source,這兩個類屬于Okio,也是Square開源的java io補充庫,有興趣的可以去了解一下,這里就不做詳細介紹了.

3. 實現HttpClientHelper類

HttpClientHelper用于創建okhttp client,并對okhttpclient添加攔截事件,將requestBody和responseBody替換成我們自己實現的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,用于下載文件的回調* @param progressListener 進度回調接口* @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());//包裝響應體并返回return originalResponse.newBuilder().body(new ProgressResponseBody(originalResponse.body(), progressListener)).build();}});return client.build();}/*** 包裝OkHttpClient,用于上傳文件的回調* @param progressListener 進度回調接口* @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是在當前類實現了ProgressRequestListener接口 Call<ResponseBody> call = service.upload(body);

service 需要自己封裝

總結

以上是生活随笔為你收集整理的Android --- Retrofit 上传/下载文件扩展实现进度的监听的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。