多多色-多人伦交性欧美在线观看-多人伦精品一区二区三区视频-多色视频-免费黄色视屏网站-免费黄色在线

國內(nèi)最全IT社區(qū)平臺 聯(lián)系我們 | 收藏本站
阿里云優(yōu)惠2
您當(dāng)前位置:首頁 > php開源 > 綜合技術(shù) > 你必須學(xué)會的okhttp——進階篇

你必須學(xué)會的okhttp——進階篇

來源:程序員人生   發(fā)布時間:2017-01-13 11:01:14 閱讀次數(shù):4530次

今天上1篇博客恰好在郭神公眾號出現(xiàn)了。也有1個多月沒寫點甚么了。今天就繼上1次的okhttp繼續(xù)深入了解把。在你必須學(xué)會的okhttp——入門篇中我簡單介紹了okhttp的使用方法。不了解可以看完在回來看這篇文章。
好了。話不多說。這次我主要介紹下okhttp如何實現(xiàn)多文件斷點下載。
參考博客:

http://blog.csdn.net/KevinsCSDN/article/details/51934274

之前對如何使用okhttp上傳與下載我們已知道該怎樣做了。但是如何實現(xiàn)多文件的操作呢?首先,在這邊論述下我做的進程中所遇到的問題。

  • 如何存儲url對應(yīng)確當(dāng)前長度和總長度
  • 如何實現(xiàn)暫停和續(xù)傳操作
  • 如何用1個info對象實現(xiàn)多文件的下載
  • response.body.contentlength與實際長度不1樣。(例如我獲得的長度是5.5M但他的實際長度是6.7M)

如何存儲當(dāng)前長度和總長度

我在網(wǎng)上看到很多demo對這塊是用SQLite實現(xiàn),我覺得完全可以Shareperference來存儲,通過他的url來存儲對應(yīng)確當(dāng)前長度和總長度,有人回說Shareperference不是只能1個建對應(yīng)1個值么,兩個怎樣解決。我們可以通過MD5加密的url來存儲當(dāng)前進度。通過MD2加密來存儲總進度。

如何實現(xiàn)暫停和續(xù)傳操作

我們可以通過okhttp自帶的攔截器來實現(xiàn)其效果,具體代碼以下:

  private Call newCall(long current_length ) {
        Request request = new Request.Builder()
                .url(url)
                .header("RANGE", "bytes=" + current_length + "-")
                .build();
        return client.newCall(request);
    }

    public OkHttpClient getProgressClient() {
        Interceptor interceptor = new Interceptor() {
            public Response intercept(Chain chain) throws IOException {
                Response originalResponse = chain.proceed(chain.request());
                return originalResponse.newBuilder()
                        .body(originalResponse.body())
                        .build();
            }
        };

        return new OkHttpClient.Builder()
                .addNetworkInterceptor(interceptor)
                .build();
    }

如何用1個info對象實現(xiàn)多文件的下載

其實在前面我也說了。用Shareperference來實現(xiàn),具體怎樣說的。你的url,存儲路徑每次都是需要傳的,但是為了避免進度沖突(例:明明的A的進度,下載B的時候卻用的A的進度)。所以通過傳入的url來用Shareperference得到他存儲確當(dāng)前長度與總長度來解決。

response.body.contentlength與實際長度不1樣。

其實。。。我也不知道。。百度了好久。得到的答案是在HTTP協(xié)議中,消息實體長度和消息實體的傳輸長度是有區(qū)分,比如說gzip緊縮下,消息實體長度是緊縮前的長度,消息實體的傳輸長度是gzip緊縮后的長度。還有種說法還有種說法是服務(wù)器限制問題。不解。總之會致使獲得進度的時候,進度值是大于100的。。。


大致的問題和解決方法已說明了。首先,我們先來看下效果圖。
這里寫圖片描述

最后上源碼,相信你看懂了上面的思路。對源碼的理解就不是很難了。

public class DownLoadSupport {

    private OkHttpClient okHttpClient;
    private Call call;
    @Bean
    FileSupport fileSupport;
    @Bean
    ByteUtils byteUtils;
    @Bean
    SharePreferencesUtils sharePreferencesUtils;
    private MD5Utils md5Utils;

    public DownLoadSupport() {
        md5Utils = new MD5Utils();
        okHttpClient = getProgressClient();
    }

    public OkHttpClient getProgressClient() {
        Interceptor interceptor = new Interceptor() {
            public Response intercept(Chain chain) throws IOException {
                Response originalResponse = chain.proceed(chain.request());
                return originalResponse.newBuilder()
                        .body(originalResponse.body())
                        .build();
            }
        };
        return new OkHttpClient.Builder().addNetworkInterceptor(interceptor).build();
    }

    private Call newCall(HttpDownloadBean httpDownloadBean) {
        Request request = new Request.Builder().tag(md5Utils.md5(httpDownloadBean.getUrl()))
                .url(httpDownloadBean.getUrl()).addHeader("Accept-Encoding", "identity")
                .header("RANGE", "bytes=" + sharePreferencesUtils.get(md5Utils.md5(httpDownloadBean.getUrl()), (long) 0) + "-")
                .build();
        return okHttpClient.newCall(request);
    }

    public void download(final HttpDownloadBean httpDownloadBean, final DownloadCallBack callBack) {
        if (!sharePreferencesUtils.contains(md5Utils.md5(httpDownloadBean.getUrl()))) {
            sharePreferencesUtils.put(md5Utils.md5(httpDownloadBean.getUrl()), (long) 0);
        }
        if (!sharePreferencesUtils.contains(md5Utils.md2(httpDownloadBean.getUrl()))) {
            sharePreferencesUtils.put(md5Utils.md2(httpDownloadBean.getUrl()), (long) 0);
        }
        call = newCall(httpDownloadBean);
        call.enqueue(new Callback() {
            public void onFailure(Call call, IOException e) {

            }

            public void onResponse(Call call, Response response) throws IOException {
                writeToSDCard(response, httpDownloadBean, callBack);
            }
        });
    }

    public void pause(HttpDownloadBean httpDownloadBean) {
        for (Call call : okHttpClient.dispatcher().queuedCalls()) {
            if (call.request().tag().equals(md5Utils.md5(httpDownloadBean.getUrl())))
                call.cancel();
        }
        for (Call call : okHttpClient.dispatcher().runningCalls()) {
            if (call.request().tag().equals(md5Utils.md5(httpDownloadBean.getUrl())))
                call.cancel();
        }
    }

    private void writeToSDCard(Response response, HttpDownloadBean httpDownloadBean, DownloadCallBack callBack) {
        ResponseBody body = response.body();
        InputStream input = body.byteStream();
        FileChannel channelOut = null;
        // 隨機訪問文件,可以指定斷點續(xù)傳的起始位置
        RandomAccessFile randomAccessFile = null;
        long current = 0;
        long total = 0;
        current = (long) sharePreferencesUtils.get(md5Utils.md5(httpDownloadBean.getUrl()), (long) 0);
        total = (long) sharePreferencesUtils.get(md5Utils.md2(httpDownloadBean.getUrl()), (long) 0);
        if (total == 0) {
            total = body.contentLength();
            httpDownloadBean.setTotal_length(body.contentLength());
            sharePreferencesUtils.put(md5Utils.md2(httpDownloadBean.getUrl()), httpDownloadBean.getTotal_length());
        }
        try {
            randomAccessFile = new RandomAccessFile(fileSupport.createStorgeFile(httpDownloadBean.getStoragepath(), httpDownloadBean.getFilepath()), "rwd");
            //Chanel NIO中的用法,由于RandomAccessFile沒有使用緩存策略,直接使用會使得下載速度變慢,親測緩存下載3.3秒的文件,用普通的RandomAccessFile需要20多秒。
            channelOut = randomAccessFile.getChannel();
            // 內(nèi)存映照,直接使用RandomAccessFile,是用其seek方法指定下載的起始位置,使用緩存下載,在這里指定下載位置。
            MappedByteBuffer mappedBuffer = channelOut.map(FileChannel.MapMode.READ_WRITE, current, total);
            byte[] buffer = new byte[1024];
            int len;
            while ((len = input.read(buffer)) != -1) {
                current += len;
                if (callBack != null) {
                    callBack.download(byteUtils.getSize(current) + byteUtils.getByte(current), byteUtils.getSize(total) + byteUtils.getByte(total));
                    callBack.downloadprogress((int) (current * 1.0f / total * 100));
                }
                httpDownloadBean.setCurrent_length(current);
                if (current >= total) {
                    sharePreferencesUtils.remove(md5Utils.md5(httpDownloadBean.getUrl()));
                    sharePreferencesUtils.remove(md5Utils.md2(httpDownloadBean.getUrl()));
                } else {
                    sharePreferencesUtils.put(md5Utils.md5(httpDownloadBean.getUrl()), httpDownloadBean.getCurrent_length());
                }
                mappedBuffer.put(buffer, 0, len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                input.close();
                if (channelOut != null) {
                    channelOut.close();
                }
                if (randomAccessFile != null) {
                    randomAccessFile.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public interface DownloadCallBack {

        void download(String current_progress, String total_progress);

        void downloadprogress(int progress);
    }

}

關(guān)于httpdownloadbean:

`
public class HttpDownloadBean {

private String url = null;
private String storagepath = null;
private String filepath = null;
private long current_length = 0L;
private long total_length = 0L;

public long getTotal_length() {
    return total_length;
}

public void setTotal_length(long total_length) {
    this.total_length = total_length;
}

public long getCurrent_length() {
    return current_length;
}

public void setCurrent_length(long current_length) {
    this.current_length = current_length;
}

public String getUrl() {
    return url;
}

public void setUrl(String url) {
    this.url = url;
}

public String getStoragepath() {
    return storagepath;
}

public void setStoragepath(String storagepath) {
    this.storagepath = storagepath;
}

public String getFilepath() {
    return filepath;
}

public void setFilepath(String path) {
    this.filepath = path;
}

}

“`
就是這幾個數(shù)據(jù),通過set和get來設(shè)置和獲得。
ShareperferenceUtils是關(guān)于Shareperference的工具類。filesupport是用來創(chuàng)建文件的。byteutils可以沒必要理睬。

有甚么問題可以提出來1起討論。這應(yīng)當(dāng)是年前最后1篇技術(shù)博文了。我也該為年后找工作的事件而繁忙了。

生活不易,碼農(nóng)辛苦
如果您覺得本網(wǎng)站對您的學(xué)習(xí)有所幫助,可以手機掃描二維碼進行捐贈
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關(guān)閉
程序員人生
主站蜘蛛池模板: 欧美瑟图 | 欧美性淫爽www视频播放 | 国产精品久久久久久福利漫画 | 日本不卡在线一区二区三区视频 | 亚洲免费黄色网址 | 日韩欧美伊人久久大香线蕉 | 日本免费乱人伦在线观看 | 大伊人网 | 在线视频精品播放 | 午夜免费在线观看 | 亚洲色网址 | 自拍偷拍免费视频 | 欧美天天性 | 欧美视频一区二区在线观看 | 日本www在线 | 黄大色黄美女精品大毛片 | 久久就是精品 | 国内自拍成人网在线视频 | 中文字幕亚洲无线码高清 | 成人无遮挡免费网站视频在线观看 | 国产成人在线免费视频 | 手机在线精品视频每日更新 | 亚洲高清一区二区三区久久 | 国产日韩欧美亚洲 | 日韩一区二区三区四区五区 | 91精品成人免费国产片 | 国产在线精品一区二区中文 | 免费一看一级欧美 | 最近免费的中文字幕一 | 国产成人久久精品麻豆二区 | 欧美精品高清在线观看 | 久久天天躁狠狠躁夜夜中文字幕 | 宇都宫紫苑在线视频 | 免费观看美女的网站 | 国产精品v片在线观看不卡 国产精品v在线播放观看 | 最新欧美一级视频 | 2020亚洲天堂 | 亚洲综色 | 免费jizz在线播放视频高清版 | 波多野结衣高清videossex | 麻豆影视大全 |