這篇文章主要介紹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進度怎么獲取”這篇文章的所有內容,感謝各位的閱讀!希望分享的內容對大家有幫助,更多相關知識,歡迎關注創新互聯行業資訊頻道!
名稱欄目:Okhttp、Retrofit進度怎么獲取
地址分享:http://www.yijiale78.com/article40/jjpdeo.html
成都網站建設公司_創新互聯,為您提供服務器托管、ChatGPT、網站營銷、關鍵詞優化、網站改版、標簽優化
聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯