国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > Android > 正文

Okhttp、Retrofit進度獲取的方法(一行代碼搞定)

2019-10-22 18:13:15
字體:
來源:轉載
供稿:網友

起因

對于廣大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熟悉后,人家設計的還是很棒噠。

廢話不多說,先看效果。

效果

Okhttp,進度獲取,Retrofit

實際代碼:

 //添加下載攔截器(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;}@Overridepublic 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;}@Overridepublic 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@Overridepublic MediaType contentType() {  //接口方法,返回類型  return mResponseBody.contentType();}@Overridepublic 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;}@Overridepublic 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;}@Overridepublic MediaType contentType() {  //接口方法,返回類型  return mRequestBody.contentType();}@Overridepublic 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);    }  });}@Overridepublic 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;}@Overridepublic 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;}@Overridepublic 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);      }    }  });}}

總結

以上就是具體的流程了,按照步驟其實很簡單。大家了解下挺好的,我這邊也封裝好了具體的類庫和Demo,大家可以直接依賴(查看README.md,使用簡單)。

地址:https://github.com/HoldMyOwn/TNetProgress

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VEVB武林網。


注:相關教程知識閱讀請移步到Android開發頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 云安县| 齐齐哈尔市| 湖南省| 裕民县| 宿州市| 南宁市| 仙桃市| 汨罗市| 奉新县| 沛县| 柳河县| 沙田区| 富顺县| 卫辉市| 怀柔区| 邵阳市| 时尚| 宜春市| 楚雄市| 陈巴尔虎旗| 汉源县| 孟连| 滕州市| 简阳市| 德格县| 嘉义县| 柳林县| 松溪县| 嘉祥县| 慈利县| 日照市| 庆安县| 克山县| 德惠市| 富平县| 兴隆县| 红河县| 濉溪县| 宾川县| 吴江市| 安陆市|