日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

renameto 阻塞_打造简化版文件下载器

發布時間:2024/1/23 编程问答 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 renameto 阻塞_打造简化版文件下载器 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一. 前言

Executors 是一種典型的生產者 - 消費者模式, java中的線程池是運用場景最多的并發框架,幾乎所有需要異步或并發執行任務的程序都可以使用線程池。線程池就是將線程進行池化,需要運行任務時從池中拿一個線程來執行,執行完畢,線程放回池中。 在開發過程中,合理地使用線程池能夠帶來3個好處。第一:降低資源消耗。通過重復利用已創建的線程降低線程創建和銷毀造成的消耗。

第二:提高響應速度。當任務到達時,任務可以不需要等到線程創建就能立即執行。

第三:提高線程的可管理性。線程是稀缺資源,如果無限制地創建,不僅會消耗系統資源,還會降低系統的穩定性,使用線程池可以進行統一分配、調優和監控。

有沒有一種優化后的線程池方案可以進行統一的分配、調優和監控呢?今天我就帶大家手把手寫一個簡化版的線程下載器

它有如下優點支持文件下載監聽成功,失敗,暫停,下載進度回調

支持無限制添加任務到任務隊列

支持查看文件總下載大小

支持查看已經下載的大小

支持查看下載成功后的目標文件路徑

可以根據下載錯誤碼定位下載失敗原因

支持取消,暫停,開始下載任務

二. 關鍵技術

文件下載器不是很復雜,但是前提是你要對Executor一些參數要有簡單的了解下面我列了一個表格,對每個參數都詳細的介紹了一下

2.1 ThreadPoolExecutor 核心參數介紹參數名參數作用

2.1.1 RejectedExecutionHandler (飽和策閱)

線程池的飽和策略,當阻塞隊列滿了,且沒有空閑的工作線程,如果繼續提交任務,必須采取一種策略處理該任務,線程池提供了4種策略: CallerRunsPolicy AbortPolicy DiscardPolicy DiscardOldestPolicy,API文檔也給大家列好了,不記得的可以翻一翻策閱名稱策閱作用

2.1.2 workQueue (飽和策閱)

workQueue必須是BlockingQueue阻塞隊列。當線程池中的線程數超過它的corePoolSize的時候,線程會進入阻塞隊列進行阻塞等待。通過workQueue,線程池實現了阻塞功能

那么什么是阻塞隊列呢?

阻塞隊列常用于生產者和消費者的場景,生產者是向隊列里添加元素的線程,消費者是從隊列里取元素的線程。阻塞隊列就是生產者用來存放元素、消費者用來獲取元素的容器。Java提供的阻塞隊列如下:阻塞隊列名稱概念

阻塞隊列怎么實現增刪改查呢?

這里表格也給大家準備好了:

2.2 如何創建一個線程池

所有的API介紹都一一和大家介紹了,那么我們該如何傳建線程池呢,創建線程池有五種方式: 定長線程池 , 可緩存的線程池 , 單線程的線程池還有長線程池,具體應用場景如下:

2.2.1 創建一個定長線程池,可控制線程最大并發數,超出的線程會在隊列中等待。

2.2.2 根據所需的并發數來動態創建和關閉線程。能夠合理的使用CPU進行對任務進行并發操作,所以適合使用在很耗時的任務。注意返回的是ForkJoinPool對象。

2.2.3 創建一個可緩存的線程池,可靈活回收空閑線程,若無可回收,則新建線程。

2.2.4 創建一個單線程的線程池

2.2.5. 創建一個定長線程池,支持定時及周期性任務執行。

2.3 ThreadPoolExecutor 源碼結構

2.4 線程池的工作原理如果當前運行的線程少于corePoolSize,則創建新線程來執行任務(注意,執行這一步驟需要獲取全局鎖)如果運行的線程等于或多于corePoolSize,則將任務加入BlockingQueue。如果無法將任務加入BlockingQueue(隊列已滿),則創建新的線程來處理任務(注意,執行這一步驟需要獲取全局鎖)。如果創建新線程將使當前運行的線程超出maximumPoolSize,任務將被拒絕,并調用RejectedExecutionHandler.rejectedExecution()方法。

整體來說: 在 線程池 的內部,我們維護了一個阻塞隊列 workQueue 和一組工作線程,工作線程的個數由構造函數中的 poolSize 來指定。用戶通過調用 execute() 方法來提交 Runnable 任務,execute() 方法的內部實現僅僅是將任務加入到 workQueue 中。線程池 內部維護的工作線程會消費 workQueue 中的任務并執行任務,里面是一個 while 循環。

2.5 如何關閉線程池:

2.5.1 shutDown

shutdown調用的是advanceRunState(SHUTDOWN),而shutdownNow調用的是(STOP),即調用后設置的線程池狀態不同

2.5.2 shutDownNow

shutdown調用的是中斷空閑的Workers,而shutdownNow調用的是中斷所有的Workers shutdownNow會把所有任務隊列中的任務取出來,返回一個任務列表。而shutdown什么都不返回。

2.6 如何合理的配置線程池

要想合理地配置線程池,就必須首先分析任務特性要想合理地配置線程池,就必須首先分析任務特性任務的性質:CPU密集型任務、IO密集型任務和混合型任務。

任務的優先級:高、中和低。

任務的執行時間:長、中和短。

任務的依賴性:是否依賴其他系統資源,如數據庫連接。

2.6.1 確定核心線程數

混合型的任務,如果可以分成一個CPU密集型任務和一個IO密集型任務,只要這兩個任務執行的時間相差不是太大,那么分解后執行的吞吐量將高于串行執行的吞吐量。如果這兩個任務執行時間相差太大,則沒必要進行分解。可以通過Runtime.getRuntime().availableProcessors()方法獲得當前設備的CPU個數。

private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();

//核心線程數量大小

private static final int corePoolSize = Math.max(2, Math.min(CPU_COUNT - 1, 4));

2.6.2 確定線程池最大容納線程數

由于IO密集型任務線程并不是一直在執行任務,則應配置盡可能多的線程,如2*Ncpu。

private static final int maximumPoolSize = CPU_COUNT * 2 + 1;

2.6.3 線程池的創建

private static ThreadPoolProxy mBackgroundPool = null;

private static final Object mBackgroundLock = new Object();

private static ThreadPoolProxy mDownloadPool = null;

private static final Object mDownloadLock = new Object();

private static Map mMap = new HashMap<>();

private static final Object mSingleLock = new Object();

2.6.3.0 線程池策閱ThreadPoolProxy

public static class ThreadPoolProxy {

private ThreadPoolExecutor mPool;

private int mCorePoolSize;

private int mMaximumPoolSize;

private long mKeepAliveTime;

private boolean mIsPriority;

/**

* @param corePoolSize 核心線程數量

* @param maximumPoolSize 最大線程數量

* @param keepAliveTime 空閑線程存活時間,秒

*/

private ThreadPoolProxy(int corePoolSize, int maximumPoolSize, long keepAliveTime, boolean isPriority) {

mCorePoolSize = corePoolSize;

mMaximumPoolSize = maximumPoolSize;

mKeepAliveTime = keepAliveTime;

mIsPriority = isPriority;

}

執行任務,當線程池處于關閉,將會重新創建新的線程池

public synchronized void execute(Runnable run) {

if (run == null) {

return;

}

if (mPool == null || mPool.isShutdown()) {

//ThreadFactory是每次創建新的線程工廠

if (mIsPriority) {//使用優先級隊列

mPool = new ThreadPoolExecutor(mCorePoolSize, mMaximumPoolSize, mKeepAliveTime, TimeUnit.SECONDS, new PriorityBlockingQueue<>(), Executors.defaultThreadFactory(), new AbortPolicy());

} else {//隊列任務

mPool = new ThreadPoolExecutor(mCorePoolSize, mMaximumPoolSize, mKeepAliveTime, TimeUnit.SECONDS, new LinkedBlockingQueue<>(), Executors.defaultThreadFactory(), new AbortPolicy());

}

}

mPool.execute(run);

}

取消線程池中某個還未執行的任務

public synchronized void remove(Runnable run) {

if (mPool != null && (!mPool.isShutdown() || mPool.isTerminating())) {

mPool.getQueue().remove(run);

}

}

/**

* 是否包含某個任務

*/

public synchronized boolean contains(Runnable run) {

if (mPool != null && (!mPool.isShutdown() || mPool.isTerminating())) {

return mPool.getQueue().contains(run);

} else {

return false;

}

}

關閉線程池

/**

* 關閉線程池,

*

* @param isNow if true 立即終止線程池,并嘗試打斷正在執行的任務,清空任務緩存隊列,返回尚未執行的任務。

* if false ,確保所有已經加入的任務都將會被執行完畢才關閉,后面不接受任務

**/

public synchronized void shutdown(boolean isNow) {

if (mPool != null && (!mPool.isShutdown() || mPool.isTerminating())) {

if (isNow) {

mPool.shutdownNow();

} else {

mPool.shutdown();

}

}

}

}

}

2.6.3.1 CPU密集型獲取后臺線程池,核心線程會一直存活。

CPU密集型任務應配置盡可能小的線程,如配置Ncpu+1個線程的線程池。

public static ThreadPoolProxy getBackgroundPool() {

synchronized (mBackgroundLock) {

if (mBackgroundPool == null) {

mBackgroundPool = new ThreadPoolProxy(corePoolSize, maximumPoolSize, 60L, false);

}

return mBackgroundPool;

}

}

2.6.3.2 并發線程池

獲取一個用于文件并發下載的線程池,修改核心線程數和最大線程數

public static ThreadPoolProxy getDownloadPool() {

synchronized (mDownloadLock) {

if (mDownloadPool == null) {

mDownloadPool = new ThreadPoolProxy(4, 12, 60L, true);

}

return mDownloadPool;

}

}

2.6.3.3 單線程池

獲取一個單線程池,所有任務將會被按照加入的順序執行,免除了同步開銷的問題

public static ThreadPoolProxy getSinglePool(String name) {

synchronized (mSingleLock) {

ThreadPoolProxy singlePool = mMap.get(name);

if (singlePool == null) {

singlePool = new ThreadPoolProxy(0, 1, 60L, false);

mMap.put(name, singlePool);

}

return singlePool;

}

}

三. 簡易版下載器實現

3.0.1 定義當前下載任務枚舉狀態 DownloadStatus枚舉名意義

3.0.2 url,斷點下載開關,線程優先級,連接、讀取超時時間動態配置

public class DownloadConfig {

public String url;//下載地址,唯一標示

public String targetPath;//下載成功后的文件路徑

public int intervalTime = 1000;//默認每秒回調一次

public boolean isCallBackInUIThread = true;//默認回調在主線程

public boolean isRange = true;//是否開啟斷點下載的功能,默認開啟

public int timeOutMillisecond = 30 * 1000;//連接、讀取超時時間

public int priority;//默認線程優先級0,普通任務0,so庫下載優先級8,其他更加情況自定義

public DownloadConfig(String url, String targetPath, boolean isRange, boolean isCallBackInUIThread, int intervalTime, int timeOutMillisecond) {

this.url = url;

this.targetPath = targetPath;

this.isRange = isRange;

this.isCallBackInUIThread = isCallBackInUIThread;

this.intervalTime = intervalTime;

this.timeOutMillisecond = timeOutMillisecond;

}

3.0.3 定制化下載任務接口 BaseDownloadTask方法名作用類型

3.0.4 下載器執行文件下載接口化

public interface IDownloader{

void downloadFile(DownloadTask task);

}

3.0.5 配置下載監聽器,提供監聽成功,失敗,暫停,下載進度回調 DownloadListener方法名作用參數介紹

3.0.6 封裝單個下載任務

單任務Task實現了我們的 Runnable ,里面主要是執行我們的任務,Comparable 給我們的任務設定優先級,BaseDownloadTask 就是給任務做一些簡單的任務開始,結束,暫停,取消下載等工作了

3.0.6.1 DownloadTask 成員變量

DownloadTask 成員變量需要關注幾個點:字段名作用類型

3.0.6.2 DownloadTask 構造方法

DownloadTask 構造方法有兩個,一個是將外部自定義所有參數塞到DownloadConfig,一個是直接將參數傳到DownloadTask里面

public DownloadTask(DownloadConfig config) {

this(config.url, config.targetPath, config.isRange, config.isCallBackInUIThread, config.intervalTime, config.timeOutMillisecond, config.priority);

}

public DownloadTask(String url, String targetPath, boolean isRange, boolean isCallBackInUIThread, int intervalTime, int timeOutMillisecond, int priority) {

this.url = url;

this.targetPath = targetPath;

this.isRange = isRange;

this.isCallBackInUIThread = isCallBackInUIThread;

this.intervalTime = intervalTime;

this.timeOutMillisecond = timeOutMillisecond;

if (this.intervalTime <= 0) {

this.intervalTime = 1000;

}

if (this.timeOutMillisecond <= 0) {

this.timeOutMillisecond = 30 * 1000;

}

this.status = DownloadStatus.STATUS_NONE;

this.tempFilePath = this.targetPath + tempSuffex;

this.priority = priority;

}

3.0.6.3 DownloadTask 添加任務add()

當添加任務時候,我們給下載任務狀態置為等待,然后在這個方法里面初始化下載成功后的文件路徑以及對應的文件名

@Override

public DownloadTask add() {

status = DownloadStatus.STATUS_WAITING;

final File file = new File(targetPath);

fileName = file.getName();

return this;

}

3.0.6.4 DownloadTask run() => 任務開始start()

如果下載緩存路徑合法,將該當前本地已下載的size返回業務層

@Override

public long getDownloadedSize() {

if (!TextUtils.isEmpty(tempFilePath)) {

File file = new File(tempFilePath);

downloadedSize = file.exists() ? file.length() : 0;

} else {

downloadedSize = 0;

}

return downloadedSize;

}

3.0.6.5 設置Range斷點下載開關

如果配置了開啟斷點下載,且已經下載過,設置Range.否則關閉斷點下載

public boolean isRangeRequest() {

return isRange && getDownloadedSize() > 0;

}

3.0.6.6 compareTo 比較任務的優先級

@Override

public int compareTo(DownloadTask o) {//任務執行優先級排序

if (this.getPriority() < o.priority) {

return 1;

}

if (this.getPriority() > o.priority) {

return -1;

}

return 0;

}

3.0.6.7 DownloadTask run() => 開始下載任務start()

執行任務開始的時候,重置任務狀態,然后在run()方法里面調用下載器FileDownloader執行任務下載

@Override

public void start() {

//狀態重置

this.status = DownloadStatus.STATUS_NONE;

//開始下載

if (downloader == null) {

downloader = new FileDownloader();

}

downloader.downloadFile(this);

}

3.0.6.8 DownloadTask 暫停下載任務 pause()

在暫停下載任務方法里,將下載任務設置為暫停狀態,然后用下載監聽器將本地問價大小和總文件大小回傳給業務層

@Override

public void pause() {

status = DownloadStatus.STATUS_PAUSED;

if (listener != null) {

listener.onPaused(this, soFarBytes, totalSize);

}

}

3.0.6.9 DownloadTask 取消下載任務 pause()

取消下載任務非常簡單,將下載任務設置為取消,然后刪除所有的副本文件

@Override

public void cancel() {

status = DownloadStatus.STATUS_NONE;

//刪除臨時文件

FileUtils.deleteFile(tempFilePath);

}

3.0.7.0 DownloadTask 設置DownloadListener下載監聽器 setListener()

@Override

public DownloadTask setListener(DownloadListener listener) {

this.listener = listener;

return this;

}

還有一些常用的方法就不一一貼代碼了,詳細API文檔如下:方法名作用類型

3.0.7 封裝文件下載器FileDownloader,支持斷點下載

3.0.7.1 FileDownloader文件下載器 處理單一任務文件下載 downloadFile

downloadFile 整體看起來是比較簡單的,主線程的Looper是在這里初始化的,在這里我們默認不走下載成功回調,接著我們看看downloadByHttpURLConn是如何實現的

@Override

public void downloadFile(DownloadTask task) {

if (task == null) return;

if (handler == null) {

handler = new Handler(Looper.getMainLooper());

}

hasCallbackSuccess = false;

downloadByHttpURLConn(task);

}

3.0.7.2 downloadByHttpURLConn

downloadByHttpURLConn是 使用系統API下載,如果服務端支持206分段請求,可以斷點下載

在這里我們將下載狀態置為 STATUS_DOWNLOADING ,并且創建 HttpURLConnection 建立 Http 連接,下載我們默認使用的是 GET 請求,并且整個連接處于Keep-Alive 長連接狀態,不設置緩存,可配置化斷點下載入口

task.status = DownloadTask.DownloadStatus.STATUS_DOWNLOADING;

HttpURLConnection conn = null;

InputStream inputStream = null;

try {

URL url = new URL(task.url);

conn = (HttpURLConnection) url.openConnection();

conn.setRequestMethod("GET");

conn.setConnectTimeout(task.timeOutMillisecond);

conn.setReadTimeout(task.timeOutMillisecond);

conn.setRequestProperty("Connection", "Keep-Alive");

conn.setRequestProperty("Cache-Control", "no-cache");

conn.setRequestProperty("pragma", "no-cache");

conn.setRequestProperty("Accept", "*/*");

//是否開啟range請求,code=416,表示請求范圍不對

String rangStr = "";

if (task.isRangeRequest()) {//isRangeRequest()方法里面會獲取最新的本地緩存文件downloadedSize大小

rangStr = "bytes=" + task.downloadedSize + "-";

conn.setRequestProperty("Range", rangStr);//+ task.totalSize

//Logger.d(TAG, "isRangeRequest" + task.downloadedSize);

}獲取服務器返回的狀態碼

//獲取服務器返回的狀態碼

int code = conn.getResponseCode();

if (200 == code || 206 == code) { //200 請求服務器資源全部返回成功 //206 請求部分服務器資源返回成功

final String length = conn.getHeaderField("Content-Length");

if (!TextUtils.isEmpty(length)) {//總長度

task.totalSize = Long.parseLong(length);

}

if (task.totalSize == 0) {

final String transferEncoding = conn.getHeaderField("Transfer-Encoding");

task.isChunk = (transferEncoding != null && transferEncoding.equals("chunked"));

task.totalSize = TOTAL_VALUE_IN_CHUNKED_RESOURCE;

}

Map> map = conn.getHeaderFields();

//Logger.d(TAG, "code=" + code + ",length=" + length);

inputStream = conn.getInputStream();

startWriteFile(task, code, inputStream, rangStr, map);

} else {//出錯

task.errorCode = code;

if (416 == code) {//請求分段range有誤,本地臨時文件大小已經是有問題的

//刪除臨時文件

FileUtils.deleteFile(task.tempFilePath);

}

handleError(task, new Throwable("net request error code=" + code + "|" + rangStr + "|url:" + task.url + "|tempFile:" + task.targetPath));

}200 請求服務器資源全部返回成功

206 請求部分服務器資源返回成功Content-Length 文件總大小等于0,我們取消當前文件下載任務

非正常碼416請求分段range有誤,本地臨時文件大小已經是有問題的,我們要刪除臨時文件

不要在出錯的時候暴力刪除本地緩存

private void handleError(final DownloadTask downloadTask, final Throwable e) {

if (downloadTask == null) return;

downloadTask.status = DownloadTask.DownloadStatus.STATUS_ERROR;

DownloadManager.init().removeTask(downloadTask.url);

if (downloadTask.isCallBackInUIThread) {

handler.post(() -> {

Logger.d(TAG, "download error " + e + ",isCallBackInUIThread=" + downloadTask.isCallBackInUIThread);

if (downloadTask.listener != null) {

downloadTask.listener.onError(downloadTask, e);

}

});

} else {

if (downloadTask.listener != null) {

downloadTask.listener.onError(downloadTask, e);

}

}

}

當然我們不要在最好忘記關流和取消http連接

finally {

if (conn != null) conn.disconnect();

if (inputStream != null) {

try {

inputStream.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

3.0.7.3 startWriteFile 寫文件

在downloadByHttpURLConn 成功返回碼有一個寫文件的方法startWriteFile,如果服務器支持206分段請求,寫文件用RandomAccessFile

寫文件的邏輯比較簡單,首先得刪除目標文件,然后在構建一個副本文件如果是200所以不用做斷點續傳處理

if (200 == code) {//非range請求

tempFile.delete();

downloadTask.downloadedSize = 0;

fileOutputStream = new FileOutputStream(tempFile);

}如果是206,斷點續傳

(206 == code) {//斷點續傳

currentSize = tempFile.length();

downloadTask.downloadedSize = currentSize;

raf = new RandomAccessFile(tempPath, "rw");

raf.seek(currentSize);

Logger.d(TAG, "206 range downloadedSize=" + currentSize + ",totalSize=" + downloadTask.totalSize);

}

然后執行文件讀寫工作,中間有三個注意事項

while ((len = inputStream.read(buffer)) != -1 && DownloadTask.DownloadStatus.STATUS_DOWNLOADING == downloadTask.status) {

if (200 == code) {

fileOutputStream.write(buffer, 0, len);

fileOutputStream.flush();

} else if (206 == code) {

raf.write(buffer, 0, len);

}

}每intervalTime毫秒回調一次,完成了下載必須回調

soFarBytes += len;

downloadTask.downloadedSize = currentSize + soFarBytes;

downloadTask.soFarBytes = soFarBytes;

if (System.currentTimeMillis() - start >= downloadTask.intervalTime || soFarBytes == downloadTask.totalSize) {

notifyProgress(downloadTask, soFarBytes);

start = System.currentTimeMillis();

}

}本地文件大小和服務器文件大小一樣,說明文件下載完畢執行下載成功回調

if (downloadTask.soFarBytes == downloadTask.totalSize) {

handleSuccess(downloadTask);

}寫文件出錯了,停止下載,回調錯誤.如果是塊傳輸,totalSize不是實際總大小

if (downloadTask.totalSize > 0 && downloadTask.soFarBytes > downloadTask.totalSize && !downloadTask.isChunk) {

String errorMsg = ERROR_DOWNLOAD_MORE_SIZE + " localSize=" + downloadTask.downloadedSize +

",soFar=" + downloadTask.soFarBytes + ",total=" + downloadTask.totalSize;

Logger.d(TAG, errorMsg);

downloadTask.cancel();

handleError(downloadTask, new RuntimeException(errorMsg));

}如果STATUS_DOWNLOADING下載狀態的文件,沒有回調成功,則回調失敗

if (DownloadTask.DownloadStatus.STATUS_DOWNLOADING == downloadTask.status) {

if (!hasCallbackSuccess &&

(!downloadTask.isChunk && downloadTask.soFarBytes == downloadTask.totalSize)) {

//非Chunk下載,并且下載的大小和總大小一致回調成功

handleSuccess(downloadTask);

} else if (!hasCallbackSuccess && downloadTask.isChunk) {

//Chunk下載,暫時可以認為成功

handleSuccess(downloadTask);

} else {

//失敗

StringBuilder headStr = new StringBuilder();

if (null != map) {

for (String key : map.keySet()) {

headStr.append("|").append(key).append("=").append(map.get(key).toString());

}

}

handleError(downloadTask, new Throwable("Error WriteFile,hasCallSuc:" + hasCallbackSuccess + "|headerStr:" + headStr + "|bytes:" + downloadTask.soFarBytes + "-" + downloadTask.totalSize + "-" + downloadTask.downloadedSize +

"|" + rangStr + "|url:" + downloadTask.url + "|tempFile:" + tempFile.getPath() + "-" + tempFile.length()));

}

}

3.0.7.4 進度通知回調 notifyProgress

如果當前任務在主線程中運行,那么我們就把下載進度更新操作切換到UI線程

private void notifyProgress(final DownloadTask downloadTask, final long soFarBytes) {

if (DownloadTask.DownloadStatus.STATUS_DOWNLOADING == downloadTask.status) {

if (downloadTask.isCallBackInUIThread) {

handler.post(() -> {

if (downloadTask.listener != null) {

downloadTask.listener.onProgress(downloadTask.downloadedSize, soFarBytes, downloadTask.totalSize);

}

});

} else {

if (downloadTask.listener != null) {

downloadTask.listener.onProgress(downloadTask.downloadedSize, soFarBytes, downloadTask.totalSize);

}

}

}

}

3.0.7.5 下載成功回調 handleSuccess

如果是分段傳輸,我們要保證一點下載文件大小要等于總文件大小 下載成功后,重命名,去除.temp臨時文件,并且將該鏈接下載任務從隊列移除,然后將成功下載回調給業務層

private void handleSuccess(final DownloadTask downloadTask) {

if (downloadTask == null) return;

if (hasCallbackSuccess) return;

downloadTask.status = DownloadTask.DownloadStatus.STATUS_DOWNLOADED;

if (downloadTask.isChunk) {

downloadTask.totalSize = downloadTask.downloadedSize;//保證最后完成下載時的文件大小回調

}

//完整下載后,重命名,去除.temp臨時文件

final File targetFile = new File(downloadTask.targetPath);

if (targetFile.exists()) {

targetFile.delete();

}

final File tempDownloadedFile = new File(downloadTask.tempFilePath);

tempDownloadedFile.renameTo(targetFile);

//Log.d("dq-handleSuccess", targetFile.getName() + ",url=" + downloadTask.url);

DownloadManager.init().removeTask(downloadTask.url);

if (downloadTask.isCallBackInUIThread) {

handler.post(() -> {

if (downloadTask.listener != null) {

downloadTask.listener.onSuccess(downloadTask);

}

});

} else {

if (downloadTask.listener != null) {

downloadTask.listener.onSuccess(downloadTask);

}

}

hasCallbackSuccess = true;

}

3.0.7.6 下載失敗回調 handleSuccess

不要在出錯的時候暴力刪除本地緩存,這樣可能其他回調會受到影響

private void handleError(final DownloadTask downloadTask, final Throwable e) {

if (downloadTask == null) return;

downloadTask.status = DownloadTask.DownloadStatus.STATUS_ERROR;

DownloadManager.init().removeTask(downloadTask.url);

if (downloadTask.isCallBackInUIThread) {

handler.post(() -> {

Logger.d(TAG, "download error " + e + ",isCallBackInUIThread=" + downloadTask.isCallBackInUIThread);

if (downloadTask.listener != null) {

downloadTask.listener.onError(downloadTask, e);

}

});

} else {

if (downloadTask.listener != null) {

downloadTask.listener.onError(downloadTask, e);

}

}

}

3.0.8 下載管理器 DownloadManager 封裝

3.0.8.1 DownloadManager()

DownloadManager 構造器主要拿到主線程的Looper, 以及初始化普通的下載線程池

private DownloadManager() {

mTaskMap = new ConcurrentHashMap<>();

mHandler = new Handler(Looper.getMainLooper());

downloadPool = ThreadManager.getDownloadPool();//普通的下載線程池;

}

3.0.8.2 init()

DownloadManager 是一個最簡單的單例實現,我們獲取DownloadManager 引用直接調用init 即可

public static DownloadManager init() {

return SingletonHolder.INSTANCE;

}

3.0.8.3 download() 文件下載

初始化文件下載任務,加入下載的線程池,默認在子線程回調的下載任務

/**

* 方便外部自定義所有參數

*

* @param config 下載參數,可擴展

* @param listener 下載監聽,回調

* @return 返回當前下載任務

*/

public synchronized DownloadTask download(DownloadConfig config, DownloadListener listener) {

if (config == null || TextUtils.isEmpty(config.url) || TextUtils.isEmpty(config.targetPath)) {

throw new NullPointerException();

}

final DownloadTask downloadTask = new DownloadTask(config)

.setListener(listener)

.add();

addToDownloader(downloadTask);

return downloadTask;

}

public synchronized DownloadTask download(String url, String targetPath, boolean isRange, boolean isCallBackInUIThread, int intervalTime, int timeOutMillisecond, DownloadListener listener) {

if (TextUtils.isEmpty(url) || TextUtils.isEmpty(targetPath)) {

throw new NullPointerException();

}

final DownloadTask downloadTask = new DownloadTask(url, targetPath, isRange, isCallBackInUIThread, intervalTime, timeOutMillisecond, 0)

.setListener(listener)

.add();

addToDownloader(downloadTask);

return downloadTask;

}

3.0.8.4 添加下載任務

如果下載的文件有版本差異,下載前請清除緩存文件,防止出現不同時段寫入文件,導致錯誤

public synchronized void addToDownloader(DownloadTask task) {

if (task == null || TextUtils.isEmpty(task.url)) {

throw new NullPointerException();

}

DownloadTask downloadTask = mTaskMap.get(task.url);

if (downloadTask == null) { // 創建一個新的下載任務,放入線程池

mTaskMap.put(task.url, task);

downloadPool.execute(task);

//Logger.d(TAG, "dq-start download:" + task.getUrl());

} else {

downloadTask.pause();

downloadTask.setListener(task.listener);//重新設置監聽

downloadPool.remove(downloadTask);

downloadPool.execute(downloadTask);//直接執行

}

}

3.0.8.5 暫停下載 pause

public synchronized boolean pause(String url) {

if (!TextUtils.isEmpty(url)) {

DownloadTask downloadTask = mTaskMap.get(url);

if (downloadTask != null) {

downloadTask.setListener(null);

downloadTask.pause();

removeTask(url);

//Logger.d(TAG, "pause download:" + downloadTask);

return true;

}

}

return false;

}

3.0.8.6 取消下載 cancel

取消下載,將監聽器置為null,然后清除已經下載文件,最后在線程池池里面remove task 即可

public synchronized void cancel(String url) {

if (TextUtils.isEmpty(url)) {

throw new NullPointerException();

}

DownloadTask downloadTask = mTaskMap.get(url);

if (downloadTask != null) {

downloadTask.setListener(null);

downloadTask.cancel();//會清除已經下載的文件

removeTask(url);

//Logger.d(TAG, "cancel download:" + downloadTask);

}

}

3.0.8.7 清除task緩存 removeTask

清除任務比較簡單,直接在線程池里面remove task 即可

public synchronized DownloadTask removeTask(String url) {

final DownloadTask downloadTask = mTaskMap.remove(url);

if (downloadTask != null) {

downloadPool.remove(downloadTask);

}

return downloadTask;

}

3.0.8.8 程序退出時停止下載任務 onAppExit

退出應用程序前務必清除所有任務隊列暫停然后清除里面所有的任務

public synchronized void onAppExit() {

for (DownloadTask downloadTask : mTaskMap.values()) {

downloadTask.setListener(null);

downloadTask.pause();

downloadPool.remove(downloadTask);

}

mTaskMap.clear();

downloadPool.shutdown(true);

}

總結

以上是生活随笔為你收集整理的renameto 阻塞_打造简化版文件下载器的全部內容,希望文章能夠幫你解決所遇到的問題。

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

久久这里只有精品9 | 中文字幕在线影院 | 免费精品视频 | 中文字幕亚洲情99在线 | 国产福利精品一区二区 | 色婷婷五 | 高清av免费看 | 国产精品av电影 | zzijzzij亚洲成熟少妇 | 99精品欧美一区二区三区 | 不卡av电影在线 | 国产视频精品网 | www.五月激情.com| 久操视频在线 | 国产免费黄视频在线观看 | 国产理论片在线观看 | 在线观看中文字幕亚洲 | 欧美激情精品久久久久久免费 | 久久深夜福利免费观看 | 成片免费 | 久久免费视频这里只有精品 | 久久在线免费观看视频 | 久草在线观 | 九九九热精品免费视频观看网站 | 免费看一级特黄a大片 | 在线高清 | 91亚洲欧美 | 免费看一级一片 | 天天操天天射天天 | 五月婷久 | 国产精品久久久久免费 | 欧美精品被 | www亚洲精品 | 三级黄色理论片 | 久久99热这里只有精品国产 | 久久久免费播放 | 91免费高清 | 日韩精品视频一二三 | 成人在线播放网站 | 婷婷久草 | 91一区在线观看 | 欧美午夜视频在线 | 欧美 高跟鞋交 xxxxhd | 国产精品日韩久久久久 | 亚洲丝袜一区二区 | 狠狠做深爱婷婷综合一区 | 在线视频 国产 日韩 | 国产18精品乱码免费看 | 久久精品8 | 欧美 激情在线 | 免费看片亚洲 | www.xxxx变态.com | 久久av在线播放 | 成人国产一区 | 婷婷久久亚洲 | wwxxx日本| 中文在线a天堂 | 在线观看香蕉视频 | 91精品1区| 九九免费观看视频 | 精品国模一区二区三区 | 精品少妇一区二区三区在线 | 国产极品尤物在线 | 男女全黄一级一级高潮免费看 | 看国产黄色片 | 国产精品高潮在线观看 | av在线播放不卡 | 97在线免费视频观看 | 久久精品123 | 日韩网站在线免费观看 | 国产精品白浆 | 色99久久| 中文字幕一二三区 | 亚洲 综合 精品 | 日本久久久久久久久久 | 久久精品欧美日韩精品 | 麻豆免费看片 | 日韩中文字幕免费在线观看 | 亚洲电影久久久 | 91精品在线观看入口 | 国产麻豆传媒 | 国产精品乱码一区二三区 | 精品一区在线 | 国产午夜精品一区二区三区 | 成人超碰在线 | 成人综合免费 | 亚洲在线| 91精品啪在线观看国产 | 国产成人99av超碰超爽 | 蜜臀久久99静品久久久久久 | 天堂av免费观看 | 韩日精品在线 | 综合五月| 超碰人人av| 丁香色婷婷 | 精品国产一区二区三区久久久久久 | 欧美精品乱码久久久久 | 天天操夜操 | 免费高清无人区完整版 | 国产精品久久 | 日韩高清免费在线 | 日日摸日日添夜夜爽97 | 久久99视频| 亚洲午夜精品久久久久久久久久久久 | 午夜av在线电影 | 欧美日韩亚洲在线观看 | 黄色大全视频 | 91丨九色丨国产在线观看 | 一级黄色电影网站 | 黄色av在| 久久婷亚洲五月一区天天躁 | 国产婷婷视频在线 | 国产精品一区二区久久 | a级片在线播放 | 免费看久久久 | 国产精品久久久久久久久久白浆 | 黄色国产高清 | 国内精品久久久久久久久久清纯 | 久久久五月天 | 欧美另类交在线观看 | 欧美成年黄网站色视频 | 日本久久久精品视频 | 狠狠躁日日躁夜夜躁av | 玖玖视频在线 | 黄色毛片电影 | 精品久久久久久久久中文字幕 | 99精品国产aⅴ | 欧美另类高清 videos | 国产精品一区二区精品视频免费看 | 夜夜骑首页| 中文字幕在线日本 | 成人午夜黄色影院 | 日韩黄色在线观看 | www激情久久 | 免费观看全黄做爰大片国产 | 最新中文字幕 | 97看片网 | 日韩理论在线观看 | 日韩欧美在线观看一区二区 | 亚洲成免费| 偷拍区另类综合在线 | 国产欧美日韩视频 | 又爽又黄在线观看 | 国产高h视频 | 亚洲国产精品500在线观看 | 国产精品高清一区二区三区 | www一起操| 欧美日韩一级在线 | 麻豆成人在线观看 | 亚洲japanese制服美女 | 四虎国产精品免费观看视频优播 | 色视频网站在线 | 不卡的av电影 | 99精品热| 色婷婷丁香 | 亚洲男人天堂a | 一级黄色大片 | 国产资源免费 | 国产亚洲精品中文字幕 | 久久精品牌麻豆国产大山 | 国内综合精品午夜久久资源 | 亚洲精品免费在线视频 | 久久久精品日本 | 亚洲黄色在线播放 | 91少妇精拍在线播放 | 中文字幕日本电影 | 在线观看av小说 | 综合色影院 | zzijzzij亚洲成熟少妇 | 亚洲日韩欧美视频 | 国产精品毛片一区二区在线 | 国产精品理论片在线观看 | 国产精品一区免费看8c0m | 国产欧美久久久精品影院 | 91九色蝌蚪视频 | 国产三级国产精品国产专区50 | 99re中文字幕 | 国产午夜一区二区 | 天天干天天拍天天操天天拍 | 久久精品日产第一区二区三区乱码 | 国产高清视频在线观看 | 日韩电影中文,亚洲精品乱码 | 欧美在线1 | 国产伦精品一区二区三区免费 | 播五月综合| 国产黄色理论片 | 中文字幕一区二区三区乱码不卡 | 91精品视频免费观看 | 久久99操| 中文字幕av网站 | 色综合久久精品 | 国产精品麻豆一区二区三区 | 五月激情综合婷婷 | 蜜臀91丨九色丨蝌蚪老版 | 久草在线视频首页 | 九九热在线视频免费观看 | 中文字幕久久亚洲 | 天天操狠狠操网站 | 在线观看视频国产一区 | 久久污视频 | 日韩电影在线观看一区二区 | 国产一区二区三区高清播放 | 亚洲精品www久久久 www国产精品com | 色综合天天综合网国产成人网 | 婷婷六月综合亚洲 | 亚洲精品日韩一区二区电影 | 久久成人亚洲欧美电影 | 国产福利一区二区三区视频 | 国产在线不卡精品 | 欧美日本在线视频 | 国产一区免费视频 | 亚洲欧洲成人 | 欧美a级成人淫片免费看 | 91九色国产视频 | 国产成人精品午夜在线播放 | 香蕉视频国产在线 | 91爱爱网址 | 岛国大片免费视频 | 欧美黄色高清 | 天天拍天天草 | 999男人的天堂 | 午夜天使| 精品一区91| 在线观看一区二区视频 | 久久夜色精品亚洲噜噜国4 午夜视频在线观看欧美 | 一区二区精品视频 | 在线有码中文字幕 | 欧美二区视频 | 国产蜜臀av | 一区在线播放 | 国产成人av一区二区三区在线观看 | 亚洲性少妇性猛交wwww乱大交 | 最近高清中文在线字幕在线观看 | 免费v片| 天堂av在线 | 免费网站看v片在线a | 色婷婷在线播放 | avwww在线 | 欧美狠狠色 | 人人射人人澡 | www日韩| 五月婷影院 | 亚洲一级电影 | 欧美午夜久久 | 亚洲韩国一区二区三区 | 免费视频久久 | 国产精品福利午夜在线观看 | 最近高清中文在线字幕在线观看 | 五月婷婷国产 | 国产精品成人久久久 | 麻豆国产精品一区二区三区 | 中文不卡视频在线 | 91精品视频免费观看 | 色视频在线免费 | 在线亚洲天堂网 | 精品国产精品久久 | 国产一区在线播放 | 日本一区二区免费在线观看 | 精品国产日本 | 在线观看你懂的网站 | 精品国产免费人成在线观看 | 人人澡超碰碰97碰碰碰软件 | 国产精品视频最多的网站 | 日日操日日插 | 丁香花中文在线免费观看 | av日韩精品 | 国产精品免费久久久久久 | 999视频在线观看 | 人人草在线视频 | 国产一区二区成人 | 日日干干 | 青草草在线视频 | 天天鲁一鲁摸一摸爽一爽 | 久久综合欧美精品亚洲一区 | 99久久99视频只有精品 | 五月婷婷综合久久 | 日韩中文字幕视频在线观看 | 人人干狠狠干 | 免费看搞黄视频网站 | 婷婷色在线 | 在线观看国产高清视频 | 亚洲久草在线 | 免费日韩一区二区 | 国产亚洲精品福利 | 天天操导航 | 国产精品美女久久久久久 | 亚洲黄色免费观看 | 黄视频色网站 | 国产成人精品久久久久蜜臀 | 久久精品一区二区三区中文字幕 | 伊人超碰在线 | 亚洲精品久久激情国产片 | 欧美日韩视频精品 | 国产精品3区 | 91精品国产91 | 久久狠狠一本精品综合网 | 久草视频手机在线 | 久久精品永久免费 | 国产69久久久欧美一级 | 丁香视频在线观看 | 久久资源在线 | 欧美日韩精品在线播放 | 国产精品激情偷乱一区二区∴ | 国产老太婆免费交性大片 | 亚洲五月婷婷 | 国产午夜三级一区二区三桃花影视 | a亚洲视频| 一区av在线播放 | 激情视频免费在线 | 久草观看视频 | 日本黄色一级电影 | 亚洲黄色免费电影 | 久久久国产网站 | 亚洲精品一区二区三区在线观看 | 久久伊人91| 久久精品这里都是精品 | www.天天射.com | 国产精品www| 91av在线播放 | 欧美性高跟鞋xxxxhd | 久久久国产精品一区二区三区 | 成人wwwxxx视频 | 91亚洲精品久久久蜜桃网站 | 国产成人高清在线 | 在线观看免费观看在线91 | 成人a级黄色片 | 久久精品综合网 | 精品国产99国产精品 | 亚洲精品乱码久久久久 | 久久国产精品视频观看 | 激情综合中文娱乐网 | 国产一级高清 | 国产精品av免费 | 国产69熟| 国产婷婷精品av在线 | 黄色特一级片 | 国产福利91精品一区二区三区 | 欧美 日韩 成人 | 午夜精品福利一区二区三区蜜桃 | 精品亚洲欧美无人区乱码 | 丁香六月综合网 | 国产99在线播放 | 狠狠躁夜夜a产精品视频 | 久久国产日韩 | 日韩精品资源 | 亚洲无吗av | 国产精品自产拍在线观看网站 | 欧美在线视频不卡 | 91视频麻豆 | 97国产人人 | 九九热在线观看 | 97人人射 | 永久免费视频国产 | av免费播放 | avhd高清在线谜片 | 久久久国产一区二区三区 | 91麻豆精品国产91久久久久久久久 | 91在线播放综合 | 丁香五婷 | 国产在线综合视频 | 99久久久国产精品免费观看 | 丁香久久婷婷 | 成人性生活大片 | 成片人卡1卡2卡3手机免费看 | 日韩91精品| 99精品视频网站 | 亚洲电影av在线 | 亚洲精品美女视频 | 亚洲日本在线视频观看 | 国产成人黄色片 | 日韩美女免费线视频 | 在线观看中文字幕 | 久久国产精品99久久久久久老狼 | 91麻豆精品国产91久久久久久久久 | 91精品国自产在线观看欧美 | 蜜臀久久99静品久久久久久 | 天天插天天狠 | 日韩精品免费在线 | 激情影音先锋 | 国产成人在线看 | www.黄色片网站 | 992tv在线观看网站 | 99热在线这里只有精品 | 国产麻豆精品久久一二三 | 欧美在线一二 | 亚洲精品视频在线观看免费视频 | 四虎影视久久久 | 午夜精品一区二区三区在线播放 | 在线小视频 | 日韩在线视频二区 | 天天干天天射天天操 | 国产一区二区视频在线播放 | 久久久久高清毛片一级 | 在线观看av黄色 | 久久久久麻豆v国产 | 国产一区在线免费 | 免费下载高清毛片 | 成人在线观看影院 | 香蕉网站在线观看 | 91成版人在线观看入口 | 婷婷色视频 | 九色91av | av成人在线看 | 国产中文伊人 | 六月色丁香 | 18国产精品白浆在线观看免费 | 日本在线观看一区二区三区 | 中文字幕日本在线 | 中文字幕超清在线免费 | 日日爽视频 | 国产高清av免费在线观看 | 黄色免费看片网站 | 国产黄色电影 | 天天操天天干天天操天天干 | 婷婷激情五月综合 | 91香蕉视频黄 | 99久久精品费精品 | www.婷婷色 | 很黄很污的视频网站 | 亚洲色图av| 日韩av快播电影网 | 日韩精品视频免费在线观看 | 国产亚洲精品女人久久久久久 | 亚洲精品久久久久中文字幕m男 | 亚洲日本中文字幕在线观看 | 日韩av中文字幕在线免费观看 | 国产99久久久国产精品成人免费 | 色夜视频 | 欧美日韩视频网站 | 在线亚洲观看 | 久久综合色一综合色88 | 久久成人国产 | mm1313亚洲精品国产 | 中文字幕影片免费在线观看 | 天天草天天插 | 99精品视频一区二区 | 日韩在线视频观看免费 | 精品久久网 | 中文字幕av一区二区三区四区 | 激情五月在线 | 一区二区三区在线免费 | 人人澡超碰碰 | 日韩aa视频 | 蜜臀av夜夜澡人人爽人人桃色 | 99精品久久久久 | 不卡视频在线看 | 黄色一级影院 | 五月婷婷电影网 | 色资源网在线观看 | 午夜三级毛片 | 成人午夜电影在线观看 | 免费黄色a网站 | 日韩欧美久久 | 成人亚洲精品久久久久 | 亚洲高清在线观看视频 | 丁香婷婷激情网 | 麻豆网站免费观看 | 日韩国产精品一区 | 天天色天天爱天天射综合 | 日韩av一卡二卡三卡 | 日韩中文字幕免费看 | 国产一区二区在线播放视频 | 中文字幕免费高 | 在线观看精品视频 | 91精品国产自产在线观看 | 亚洲精品久久久久58 | 在线观看视频亚洲 | 在线观看国产v片 | 国产成a人亚洲精v品在线观看 | 干综合网| 久久艹久久 | 日韩成人精品一区二区 | 超碰在线日韩 | 特级西西444www大精品视频免费看 | 欧美精品久久久久久久久免 | 国产精品毛片久久久 | 亚洲一级片在线观看 | 91在线中字 | 99久久久国产精品免费观看 | 在线观看av片 | 国产精品6| 爱av在线网 | 99精品视频免费观看视频 | 精品久久久免费视频 | 日本动漫做毛片一区二区 | 四虎影视成人永久免费观看视频 | 一区二区三区精品在线 | 在线亚洲免费视频 | 超碰97中文| 日日夜夜精品免费观看 | 91看片看淫黄大片 | 日韩精品无码一区二区三区 | 国产在线国偷精品产拍免费yy | 国产精品乱码高清在线看 | 美女国产| 深爱五月激情五月 | 97超碰在线久草超碰在线观看 | 97超碰人人澡人人爱学生 | 亚洲最新av在线网站 | 国产在线观看你懂得 | 中文字幕在线观 | 天天天在线综合网 | 91香蕉视频好色先生 | 日韩av中文字幕在线 | 激情片av | 日韩激情视频 | 人人精品久久 | 国产视频资源 | 国产精品久久久久久久妇 | 亚洲精品黄色在线观看 | 天天草综合网 | 2018好看的中文在线观看 | 国产精品午夜在线观看 | 日韩欧美成 | 最近高清中文字幕在线国语5 | 国产一区二区在线免费 | 手机看片国产日韩 | 久久免费视频这里只有精品 | 色婷婷国产在线 | 亚洲免费在线播放视频 | 精品日韩中文字幕 | 中国成人一区 | 在线日韩av | 天天插夜夜操 | 91污视频在线 | 国产精品6| 亚洲精品成人av在线 | 欧美日韩国产一区二区三区 | 97精产国品一二三产区在线 | 国产一级黄色免费看 | 国产成人一区二区精品非洲 | 亚洲,播放 | 色婷婷国产精品一区在线观看 | 国产精品美女免费 | 国产96在线视频 | 日韩在线网址 | 天天射天天拍 | 狠狠躁夜夜躁人人爽超碰97香蕉 | 欧美日韩一级久久久久久免费看 | 亚洲视频1 | 国产精品久久久久久久久久久久冷 | 69亚洲乱 | 一区二区欧美日韩 | 开心激情五月网 | 99久热在线精品视频观看 | 欧美日韩中文视频 | 手机在线日韩视频 | 午夜影院先 | 国产三级久久久 | 亚洲国产精品电影 | 麻豆免费观看视频 | 国产精品一区二区中文字幕 | 五月综合婷 | 天天综合网在线 | 婷婷色综 | 亚洲综合狠狠干 | 香蕉视频在线免费看 | 欧美另类sm图片 | 伊人黄 | 成人毛片一区 | 国产无套视频 | 亚洲精品在线观看的 | 久久久精品久久日韩一区综合 | 亚洲aaa级 | 欧美激情视频在线观看免费 | 91刺激视频| 日韩av区 | 国内精品亚洲 | 国产高清在线一区 | 美女一级毛片视频 | 黄色亚洲精品 | 久久免费电影网 | 久久国产亚洲视频 | 欧美福利在线播放 | 亚洲一区二区三区精品在线观看 | 亚洲涩涩网站 | 国产婷婷一区二区 | 91人人澡 | 四虎国产免费 | 美女久久久 | av在线h | 欧美日韩另类在线观看 | 黄色国产在线 | 天天天在线综合网 | 久久看免费视频 | www.久久色 | 午夜久久久久久久 | 999久久久久久久久久久 | 91私密视频 | 国产很黄很色的视频 | 91成人欧美 | 免费看一级特黄a大片 | 国产999免费视频 | 婷婷婷国产在线视频 | 亚洲五月 | 99热在线免费观看 | 国产中文在线字幕 | www.天天射.com | 五月婷丁香| 成人久久精品视频 | 精精国产xxxx视频在线播放 | 久久久一本精品99久久精品66 | 久久亚洲人 | 国产91精品久久久久久 | 久久亚洲精品国产亚洲老地址 | 美女视频免费一区二区 | 一级一片免费看 | 免费日韩视频 | 色九九视频 | 欧美性生活一级片 | 国产精品午夜在线 | 狠狠狠色丁香婷婷综合久久五月 | 99精品国产免费久久久久久下载 | 国产韩国日本高清视频 | 国产成人91 | 免费观看一级 | 亚洲aⅴ免费在线观看 | 成人av电影免费观看 | 免费观看9x视频网站在线观看 | 91日韩精品一区 | 91成人精品一区在线播放69 | 91.dizhi永久地址最新 | 久久免费视频播放 | 91在线看免费 | 97在线看片 | 午夜精品一区二区三区视频免费看 | 在线观看视频黄色 | 黄色网址中文字幕 | 日本精品一 | 97视频亚洲 | 亚洲综合五月 | 成人av在线电影 | 日本在线h | 成人午夜精品久久久久久久3d | 久久午夜免费视频 | 99精品视频免费全部在线 | 久久国产精品99久久久久久丝袜 | 欧美视频网址 | 免费看一及片 | 日韩视频免费观看高清完整版在线 | 精品色999 | 伊人色综合久久天天网 | 国产在线第三页 | 欧洲不卡av| 91精品秘密在线观看 | 国产精品一区久久久久 | 亚洲 欧洲av | 又污又黄网站 | 三级小视频在线观看 | 一区二区三区在线免费观看视频 | 久久99国产精品自在自在app | 性色大片在线观看 | 国产a精品 | 毛片黄色一级 | 国产精品毛片一区二区三区 | 天天综合在线观看 | 四虎影视8848aamm | 五月婷婷六月综合 | 黄色福利网站 | 成人欧美一区二区三区在线观看 | 久久高清av | 亚洲精品欧美视频 | 一级黄色片在线观看 | 亚洲欧洲xxxx | 久久午夜色播影院免费高清 | 手机看片久久 | 久久五月天综合 | 好看的国产精品视频 | 国产一区二区三区高清播放 | 国产亚州精品视频 | 亚洲国产中文字幕在线观看 | av在线一级 | 婷婷精品在线视频 | 精品无人国产偷自产在线 | 亚洲精品在线观 | 日日爱999| 97碰视频| 成人免费一级片 | 福利视频网址 | 亚洲午夜不卡 | 亚洲免费视频在线观看 | 深爱激情五月综合 | 日韩激情一二三区 | www天天干com | 又黄又爽免费视频 | 国产69久久精品成人看 | 亚洲精品在线免费观看视频 | 美女网站黄免费 | www.av在线播放| 成年人在线播放视频 | 最新日韩电影 | 日韩欧美xxx | 99riav1国产精品视频 | 国产精品久久久久久久妇 | 国产精品乱码久久久久 | 日韩免费 | 亚洲免费av网站 | 超碰97人人在线 | 日韩av播放在线 | 欧美激情精品久久久久久免费印度 | 日韩中文字幕国产精品 | 91视频在线免费 | 500部大龄熟乱视频使用方法 | 日韩影视在线观看 | 免费一级片观看 | ww视频在线观看 | 99热这里只有精品国产首页 | 精品日韩视频 | 亚洲一区二区视频在线播放 | 麻豆超碰 | 爱爱一区 | 午夜神马福利 | 国产在线观看二区 | 黄色av一区二区三区 | 国产系列 在线观看 | 国产无限资源在线观看 | 亚洲精品视频在线观看免费视频 | 国产视频一区二区在线播放 | 国产一区电影在线观看 | 又黄又爽的视频在线观看网站 | 色av色av色av | 日p视频在线观看 | av色综合 | 在线观看一二三区 | 综合网天天射 | 一本一本久久aa综合精品 | 在线观看国产日韩 | 成人免费看片98欧美 | 一区国产精品 | 国产 日韩 欧美 中文 在线播放 | 又湿又紧又大又爽a视频国产 | 一区久久久 | 亚洲在线精品 | 国产一区在线免费观看视频 | 天堂成人在线 | 五月天国产精品 | 国产精品99视频 | 国产精品3 | 日韩精品一区二区三区外面 | 免费国产在线视频 | 国产一区二区三区午夜 | 免费日韩 精品中文字幕视频在线 | 国外成人在线视频网站 | 1000部18岁以下禁看视频 | 精品国产亚洲一区二区麻豆 | 国产亚洲片 | 成人黄大片视频在线观看 | 五月婷婷播播 | 欧美色图东方 | 激情影音先锋 | 狠狠插狠狠操 | 91丨九色丨勾搭 | av中文在线观看 | 91麻豆精品国产91久久久更新时间 | 久久久.com | 久久久久久久久影院 | 草在线视频 | 久久精品国产久精国产 | 97视频播放 | 国产精品视频最多的网站 | 91成人蝌蚪 | 日韩在线视频免费播放 | 国产高清永久免费 | 欧美aa级 | 欧美日韩一级久久久久久免费看 | 97狠狠操 | 久久国产视频网站 | 丁香婷婷综合激情 | 国产成人免费av电影 | 日韩在线播放av | 国产综合香蕉五月婷在线 | 亚洲免费av一区二区 | 青草视频在线播放 | 成人网在线免费视频 | 亚a在线 | 欧美一二三四在线 | 麻豆成人小视频 | 亚洲精品视频一二三 | 成人 亚洲 欧美 | 免费看wwwwwwwwwww的视频 久久久久久99精品 91中文字幕视频 | 久久私人影院 | 欧美在线99 | 人人爽人人 | av在线电影网站 | 久久这里只有精品1 | 欧美日韩免费在线视频 | 在线观看岛国片 | 在线看片日韩 | 成人国产在线 | av日韩不卡| 夜夜视频资源 | 色爱成人网 | 欧美黑人性猛交 | 98超碰在线| 日韩免费中文字幕 | www.久久精品视频 | 视频91在线 | 亚洲三级av | 五月天堂色 | 日韩高清精品一区二区 | 日韩理论片中文字幕 | 玖玖999 | 免费h精品视频在线播放 | 国产日产精品一区二区三区四区 | 欧美一级特黄aaaaaa大片在线观看 | 国产亚洲视频在线观看 | 丁香久久五月 | 国产高清日韩 | 免费观看国产成人 | 久久综合丁香 | 黄色免费电影网站 | 91片黄在线观看动漫 | av成人免费观看 | 中文字幕在线视频第一页 | 午夜久久成人 | 国产一区av在线 | 国产第一页在线播放 | 免费看一级特黄a大片 | 中文字幕一区2区3区 | 在线观看免费观看在线91 | 日本中文乱码卡一卡二新区 | 麻豆极品 | 日本免费久久高清视频 | 国产精品 日韩 | av电影在线观看完整版一区二区 | 国产麻豆精品久久一二三 | 麻豆视频在线免费观看 | 色网影音先锋 | 亚洲视频精选 | 亚洲精品高清一区二区三区四区 | 在线视频专区 | 亚州国产精品 | 久久精品中文视频 | 四虎影视成人永久免费观看亚洲欧美 | 国产爽视频 | 天天操天天射天天爱 | 欧美成人亚洲 | 五月开心综合 | 久久99久久久久 | av成人亚洲 | 六月丁香综合 | 欧美少妇的秘密 | 日韩精品免费一区二区 | 免费在线日韩 | 日韩欧美一区二区三区免费观看 | 在线观看资源 | 国产视频一区二区三区在线 | 国产黄在线播放 | 夜夜夜 | 日韩高清免费在线 | 久久看毛片 | 99精品免费久久久久久日本 | 免费国产在线视频 | 国产最新在线观看 | 国产成人精品三级 | 97理论电影| 99精品视频一区二区 | 人人看人人艹 | 日韩动漫免费观看高清完整版在线观看 | 黄色一级大片在线免费看国产一 | 97人人射| 国产日产在线观看 | 免费大片av| 国产一区二区久久 | 国产精品中文 | 免费十分钟| 欧美亚洲专区 | 亚洲免费精品一区二区 | 国产小视频在线观看 | 日韩欧美在线一区二区 | 久久国产精品一二三区 | 久久精品999 | 久久精品资源 | 久久久久福利视频 | 2019天天干天天色 | 日韩a欧美 | 国产区精品在线观看 | 手机av网站 | 欧美一级免费在线 | 国产精美视频 | 2019免费中文字幕 | 日韩三级.com | 国产无遮挡又黄又爽馒头漫画 | 色综合天天狠天天透天天伊人 | 亚洲在线视频观看 | 麻豆94tv免费版 | 久久免费精品视频 | 成人av影院在线观看 | 中文在线亚洲 | 三级黄色在线观看 | 欧美a影视 | 亚洲天天综合网 | 久久成人18免费网站 | 欧美日韩一区二区三区在线观看视频 | 97在线观看免费高清完整版在线观看 | 一本一道久久a久久综合蜜桃 | 一区二区三区电影在线播 | av在线网站大全 | 亚洲砖区区免费 | 久久伊99综合婷婷久久伊 | 亚洲免费国产视频 | 狠狠躁夜夜躁人人爽超碰91 | 国产视频久久久 | 国产亚洲成人网 | av在线播放国产 | 有码中文字幕在线观看 | 中文字幕中文字幕在线中文字幕三区 | 亚洲成av人片在线观看www | 涩涩网站在线观看 | 亚洲国产免费网站 | 午夜狠狠操| 美女视频黄是免费的 | 日韩视频在线不卡 | 99久久超碰中文字幕伊人 | 久久精品爱视频 | 国产亚洲字幕 | 亚洲午夜av电影 | 国产成人久久精品亚洲 | 国产亚洲视频中文字幕视频 | 天天搞天天干 | 五月婷婷一区 | 黄色大片日本 | 国产日韩欧美在线一区 | 人人草人人草 | 日韩欧美精品免费 | 亚洲国产成人久久综合 | 91欧美国产 | 在线精品观看国产 | 久久尤物电影视频在线观看 | 在线观看爱爱视频 | 成人小视频在线观看免费 | 欧美一级电影免费观看 | av中文字幕在线电影 | 久久99久久精品国产 | 亚洲黄色免费电影 | 国产小视频在线播放 | 国产精品久久免费看 | 久草在线官网 | 伊人成人激情 | 日韩欧美在线中文字幕 | 亚洲一区二区三区四区在线视频 | 久久免费久久 | 91c网站色版视频 | 最新日本中文字幕 | 午夜 久久 tv | 日韩久久精品一区二区三区下载 | 91尤物国产尤物福利在线播放 | 精品一区二区在线观看 | 国产成人精品一区二区三区福利 | 亚洲黄色一级大片 | 国模吧一区 | 欧美日韩中文字幕在线视频 | av高清一区 | 成人a级网站| av免费线看| 中文字幕乱码亚洲精品一区 | 亚洲国产精品久久久久婷婷884 | 天天干天天玩天天操 | 精品久久久网 | 国产成人精品亚洲a | 国产伦精品一区二区三区无广告 | 久久伊人综合 | 亚洲在线视频免费观看 | 国产在线精品国自产拍影院 | 六月色婷 | 人人超碰免费 | 国产成人精品一区二区三区 | 97精品欧美91久久久久久 | a级国产乱理伦片在线观看 亚洲3级 | 国产精品永久久久久久久www | 99免在线观看免费视频高清 | 日本黄网站| 日韩精品国产一区 | 69视频永久免费观看 | 激情综合五月天 | 久久不色 | 在线播放亚洲 | 久久午夜电影院 | 国产中文在线观看 | 国产精品久久久久久久久久久久 | 视频直播国产精品 | 亚洲一区二区三区91 | 亚洲成人网av | 麻豆视频免费在线观看 | 五月在线 | 丁香六月综合网 | 97在线成人 | 成人h在线| 亚洲精品自拍 | 在线观看激情av | 91麻豆文化传媒在线观看 | 免费大片黄在线 | 五月婷在线视频 | 久久久久福利视频 | 91麻豆网站 | 国产精品99在线播放 | 综合在线色 | 在线免费观看羞羞视频 |