最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

 更新時(shí)間:2018年04月03日 11:42:47   作者:Allen___  
本篇文章主要介紹了Okhttp、Retrofit進(jìn)度獲取的方法(一行代碼搞定),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧

起因

對于廣大Android開發(fā)者來說,最近用的最多的網(wǎng)絡(luò)庫,莫過于Okhttp啦(Retrofit依賴Okhttp)。

Okhttp不像SDK內(nèi)置的HttpUrlConnection一樣,可以明確的獲取數(shù)據(jù)讀寫的過程,我們需要執(zhí)行一些操作。

介紹

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是一個(gè)實(shí)現(xiàn)了java.io和java.nio的一個(gè)類庫,它讓連接,存儲,處理你的數(shù)據(jù)更加輕松~(Okio既是讀寫相關(guān)類庫,獲取進(jìn)度要從Okio入手)。

好吧,對于廣大開發(fā)者來說,內(nèi)心是這樣的:TM又要看你文檔和用例,按你規(guī)則走,輕松個(gè)毛?。?br />

其實(shí),讀下API,看下Example熟悉后,人家設(shè)計(jì)的還是很棒噠。

廢話不多說,先看效果。

效果

實(shí)際代碼:

 //添加下載攔截器(this參數(shù)是實(shí)現(xiàn)下載進(jìn)度接口的對象) 
 mDownClient = new OkHttpClient.Builder()
       //只需要一行代碼就行了
      .addNetworkInterceptor(new DownloadInterceptor(this))
      .build();
      
 //添加上傳攔截器(this參數(shù)是實(shí)現(xiàn)上傳回調(diào)接口的對象)      
 mUploadClient = new OkHttpClient.Builder()
       //只需要一行代碼就行了
      .addNetworkInterceptor(new UploadInterceptor(this))
      .build();

你只需要一行代碼是不行的!我為什么行?因?yàn)檫@是我寫的封裝類庫啊~(最后放地址)

思路

Okhttp依賴Okio進(jìn)行了數(shù)據(jù)的讀寫動作,我們需要找到Okio進(jìn)行處理。那么,如何加上呢?

Okhttp可以添加Interceptor(攔截器),我們可以通過攔截器的接口方法,獲取對應(yīng)的responseBody、requestBody對象進(jìn)行操作。然后我們就獲取了讀寫相關(guān)的實(shí)現(xiàn)方法。具體實(shí)現(xiàn)是通過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對象是對輸入流的包裝(下載讀數(shù)據(jù)),Sink是對輸出流的包裝(寫數(shù)據(jù)上傳)。

實(shí)現(xiàn)

根據(jù)需要添加下載、上傳Interceptor

   //添加下載攔截器(this參數(shù)是實(shí)現(xiàn)下載進(jìn)度接口的對象) 
  mDownClient = new OkHttpClient.Builder()
      .addNetworkInterceptor(new DownloadInterceptor(this))
      .build();
      
 //添加上傳攔截器(this參數(shù)是實(shí)現(xiàn)上傳回調(diào)接口的對象)      
 mUploadClient = new OkHttpClient.Builder()
      .addNetworkInterceptor(new UploadInterceptor(this))
      .build(); 

攔截器具體實(shí)現(xiàn)

 //下載攔截器   
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,傳入相關(guān)參數(shù),獲取進(jìn)度數(shù)據(jù)回調(diào)
  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,傳入?yún)?shù),獲取數(shù)據(jù)進(jìn)度回調(diào)
  builder.method(request.method(),new WrapRequestBody(request.body(),info,mListener));
  return builder.build();
  }
 }
responseBody、requestBody相關(guān)實(shí)現(xiàn)

//繼承ResponseBody實(shí)現(xiàn)具體方法
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;
//傳入進(jìn)度,以及監(jiān)聽對象
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() {
        //切換線程,進(jìn)行失敗回調(diào)
        mListener.onDownLoadGetContentLengthFail(mInfo);
      }
    });
  } else {
    mDoProgress = true;
  }
  return contentLength;
}

@Override
public BufferedSource source() {
  //WrapSource(繼承ForwardingSource,F(xiàn)orwardingSource實(shí)現(xiàn)了Source接口)
  if (mBufferedSource == null) {
    mInfo.setContentLength(contentLength());
     //傳入?yún)?shù),讀取具體進(jìn)度信息,并回調(diào) 
    WrapSource wrapSource = new WrapSource(mResponseBody.source(), mInfo, mListener,mDoProgress);
    mBufferedSource = Okio.buffer(wrapSource);
  }
  return mBufferedSource;
}
}

--------------------------------------分割---------------------------------------  

//繼承ResquestBody實(shí)現(xiàn)具體方法
public class WrapRequestBody extends RequestBody {
private RequestBody mRequestBody;
private OnUploadListener mListener;
private ProgressInfo mInfo;
private boolean mDoProgress;
private Handler mHandler = new Handler(Looper.getMainLooper());
 //傳入進(jìn)度,以及監(jiān)聽對象
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 {
    //上傳內(nèi)容長度,有異常走failWrok處理
    long l = mRequestBody.contentLength();
    mDoProgress = true;
    return l;
  } catch (IOException e) {
    e.printStackTrace();
    failWork();
    return -1;
  }
}
//進(jìn)行失敗處理
private void failWork() {
  mDoProgress = false;
  mHandler.post(new Runnable() {
    @Override
    public void run() {
      //切換線程,回調(diào)失敗信息
      mListener.onUploadGetContentLengthFail(mInfo);
    }
  });
}

@Override
public void writeTo(BufferedSink sink) throws IOException {
  mInfo.setContentLength(contentLength());
  // WrapSink (繼承ForwardingSink,F(xiàn)orwardingSink實(shí)現(xiàn)了Sink接口)
  ///傳入?yún)?shù),讀取具體進(jìn)度信息,并回調(diào) 
  WrapSink wrapSink = new WrapSink(sink, mInfo, mListener, mDoProgress);
  BufferedSink buffer = Okio.buffer(wrapSink);
  mRequestBody.writeTo(buffer);
  buffer.flush();
}
}
WrapSource、WrapSink相關(guān)實(shí)現(xiàn)

//繼承ForwardingSource 實(shí)現(xiàn)具體方法
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、進(jìn)度信息、監(jiān)聽進(jìn)度等信息。
  super(source);
  mSource = source;
  mInfo = info;
  mListener = listener;
  //傳入是否繼續(xù)執(zhí)行回調(diào)boolean參數(shù),如果之前執(zhí)行有異常,則不再繼續(xù)執(zhí)行回調(diào)
  mDoProgress = doProgress;
}

@Override
public long read(Buffer sink, long byteCount) throws IOException {
  //獲取具體進(jìn)度信息,來到了熟悉的具體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) {
          //切換到主線程,回調(diào)數(shù)據(jù)
          mListener.onDownLoadProgress(mInfo);
        }
      }
    });
  }
  return read;
}
}

--------------------------------------分割---------------------------------------

//繼承ForwardingSink 實(shí)現(xiàn)具體方法
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、進(jìn)度信息、監(jiān)聽進(jìn)度等信息。
  super(delegate);
  mInfo = info;
  mListener = listener;
   //傳入是否繼續(xù)執(zhí)行回調(diào)boolean參數(shù),如果之前執(zhí)行有異常,則不再繼續(xù)執(zhí)行回調(diào)
  mDoProgress = doProgress;
}

@Override
public void write(Buffer source, long byteCount) throws IOException {
  super.write(source, byteCount);
  //獲取具體進(jìn)度信息,來到了熟悉的具體IO
  long l = mInfo.getCurrentLength() + byteCount;
  mInfo.setCurrentLength(l);
  mHandler.post(new Runnable() {
    @Override
    public void run() {
      if (mDoProgress) {
        //切換到主線程,回調(diào)數(shù)據(jù)
        mListener.onUpLoadProgress(mInfo);
      }
    }
  });
}
}

總結(jié)

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

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

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Android Glide 4.0+使用詳解

    Android Glide 4.0+使用詳解

    這篇文章主要介紹了Android Glide 4.0+使用詳解,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-03-03
  • Android中Activity生命周期和啟動模式詳解

    Android中Activity生命周期和啟動模式詳解

    這篇文章主要介紹了Activity生命周期和啟動模式詳解的相關(guān)資料,需要的朋友可以參考下
    2016-07-07
  • Android開發(fā)之permission動態(tài)權(quán)限獲取詳解

    Android開發(fā)之permission動態(tài)權(quán)限獲取詳解

    這篇文章主要為大家詳細(xì)介紹了Android開發(fā)之permission動態(tài)權(quán)限獲取,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-08-08
  • 詳解Android自定義View--自定義柱狀圖

    詳解Android自定義View--自定義柱狀圖

    這篇文章主要介紹了詳解Android自定義View--自定義柱狀圖,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2016-12-12
  • Android開發(fā)之利用jsoup解析HTML頁面的方法

    Android開發(fā)之利用jsoup解析HTML頁面的方法

    這篇文章主要介紹了Android開發(fā)之利用jsoup解析HTML頁面的方法,結(jié)合實(shí)例形式分析了Android基于jsoup jar包來抓取html頁面的實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2016-03-03
  • Android開發(fā)中Activity的生命周期及加載模式詳解

    Android開發(fā)中Activity的生命周期及加載模式詳解

    這篇文章主要介紹了Android開發(fā)中Activity的生命周期及加載模式詳解的相關(guān)資料,非常不錯(cuò)具有參考借鑒價(jià)值,需要的朋友可以參考下
    2016-05-05
  • 調(diào)用startService會拋出IllegalStateException異常解決

    調(diào)用startService會拋出IllegalStateException異常解決

    這篇文章主要為大家介紹了調(diào)用startService會拋出IllegalStateException異常解決,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-07-07
  • Android基礎(chǔ)知識及線性布局介紹

    Android基礎(chǔ)知識及線性布局介紹

    大家好,本篇文章主要講的是Android基礎(chǔ)知識及線性布局介紹,感興趣的同學(xué)趕快來看一看吧,對你有幫助的話記得收藏一下
    2022-01-01
  • Android 手機(jī)獲取手機(jī)號實(shí)現(xiàn)方法

    Android 手機(jī)獲取手機(jī)號實(shí)現(xiàn)方法

    本文主要介紹Android 獲取手機(jī)號的實(shí)現(xiàn)方法,這里提供了實(shí)現(xiàn)方法,和具體操作流程,并符實(shí)現(xiàn)代碼,有需要的小伙伴可以參考下
    2016-09-09
  • 深入了解Android?IO的底層原理

    深入了解Android?IO的底層原理

    這篇文章主要介紹了深入了解Android?IO的底層原理,IO有緩沖與非緩沖?IO、直接與非直接?IO、阻塞與非阻塞?IO、同步與異步?IO等分類,具體詳情感興趣的小伙伴可以參考下面文章內(nèi)容
    2022-06-06

最新評論

合川市| 九龙城区| 苍南县| 滁州市| 阿城市| 沅陵县| 龙口市| 张家口市| 龙胜| 龙游县| 邯郸县| 绩溪县| 昭通市| 古交市| 鸡泽县| 体育| 姜堰市| 吉水县| 潮州市| 武胜县| 津市市| 五峰| 曲松县| 河西区| 治多县| 天等县| 福鼎市| 潍坊市| 垣曲县| 桑植县| 江都市| 兴义市| 行唐县| 美姑县| 丰镇市| 防城港市| 江阴市| 惠东县| 涞源县| 五寨县| 衡阳市|