下载器实现

pull/2/head
lyy 8 years ago
parent 78b76f5399
commit 5f755cf7ed
  1. 2
      downloadutil/src/main/java/com/arialyy/downloadutil/core/DownloadManager.java
  2. 90
      downloadutil/src/main/java/com/arialyy/downloadutil/core/DownloadTarget.java
  3. 201
      downloadutil/src/main/java/com/arialyy/downloadutil/core/IDownloadTarget.java
  4. 36
      downloadutil/src/main/java/com/arialyy/downloadutil/core/Task.java
  5. 7
      downloadutil/src/main/java/com/arialyy/downloadutil/core/inf/IDownloader.java
  6. 8
      downloadutil/src/main/java/com/arialyy/downloadutil/core/inf/IPool.java
  7. 17
      downloadutil/src/main/java/com/arialyy/downloadutil/core/inf/ITask.java
  8. 19
      downloadutil/src/main/java/com/arialyy/downloadutil/core/pool/CachePool.java
  9. 19
      downloadutil/src/main/java/com/arialyy/downloadutil/core/pool/ExecutePool.java
  10. 25
      downloadutil/src/main/java/com/arialyy/downloadutil/entity/DownloadEntity.java

@ -1,4 +1,4 @@
package com.arialyy.downloadutil; package com.arialyy.downloadutil.core;
import android.content.Context; import android.content.Context;

@ -1,33 +1,69 @@
package com.arialyy.downloadutil.core; package com.arialyy.downloadutil.core;
import com.arialyy.downloadutil.core.inf.IDownloader;
import com.arialyy.downloadutil.core.inf.ITask;
import com.arialyy.downloadutil.core.pool.CachePool;
import com.arialyy.downloadutil.core.pool.ExecutePool;
/** /**
* Created by lyy on 2016/8/16. * Created by lyy on 2016/8/17.
* 任务下载器提供抽象的方法供具体的实现类操作 * 下载任务调度类
*/ */
public abstract class DownloadTarget implements IDownloader, ITask { public class DownloadTarget extends IDownloadTarget {
protected CachePool mCachePool = CachePool.getInstance();
protected ExecutePool mExecutePool = ExecutePool.getInstance(); private static final Object LOCK = new Object();
private static volatile DownloadTarget INSTANCE = null;
/**
* 获取当前运行的任务数 public static DownloadTarget getInstance() {
* if (INSTANCE == null) {
* @return 当前正在执行的任务数 synchronized (LOCK) {
*/ INSTANCE = new DownloadTarget();
public int getCurrentTaskNum() { }
return mExecutePool.size(); }
} return INSTANCE;
}
/**
* 获取缓存任务数 private DownloadTarget() {
*
* @return 获取缓存的任务数 }
*/
public int getCacheTaskNum() { @Override
return mCachePool.size(); public void startTask(Task task) {
}
@Override
public void stopTask(Task task) {
}
@Override
public void cancelTask(Task task) {
}
@Override
public void reTryStart(Task task) {
}
@Override
public void createTask(String downloadUrl, String downloadPath) {
}
@Override
public Task getTask(String downloadUrl) {
return null;
}
@Override
public int getTaskState(String downloadUrl) {
return 0;
}
@Override
public void removeTask(String downloadUrl) {
}
@Override
public Task getNextTask() {
return null;
} }
} }

@ -0,0 +1,201 @@
package com.arialyy.downloadutil.core;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import com.arialyy.downloadutil.core.inf.IDownloader;
import com.arialyy.downloadutil.core.inf.ITask;
import com.arialyy.downloadutil.core.pool.CachePool;
import com.arialyy.downloadutil.core.pool.ExecutePool;
import com.arialyy.downloadutil.entity.DownloadEntity;
/**
* Created by lyy on 2016/8/16.
* 任务下载器提供抽象的方法供具体的实现类操作
*/
public abstract class IDownloadTarget implements IDownloader, ITask {
/**
* 任务开始
*/
public static final int START = 1;
/**
* 任务停止
*/
public static final int STOP = 2;
/**
* 任务失败
*/
public static final int FAIL = 3;
/**
* 任务取消
*/
public static final int CANCEL = 4;
/**
* 任务完成
*/
public static final int COMPLETE = 5;
protected CachePool mCachePool = CachePool.getInstance();
protected ExecutePool mExecutePool = ExecutePool.getInstance();
protected AutoTaskHandler mTaskHandler;
/**
* 下载失败次数
*/
protected int mFailNum = 10;
/**
* 超时时间
*/
protected long mTimeOut = 10000;
/**
* 下载器任务监听
*/
private OnTargetListener mTargetListener;
/**
* Target处理任务监听
*/
public interface OnTargetListener {
/**
* 任务开始
*
* @param task
*/
public void onTaskStart(Task task);
/**
* 任务停止
*
* @param task
*/
public void onTaskStop(Task task);
/**
* 任务取消
*
* @param task
*/
public void onTaskCancel(Task task);
/**
* 任务下载失败
*
* @param task
*/
public void onTaskFail(Task task);
/**
* 任务完成
*
* @param task
*/
public void onTaskComplete(Task task);
}
protected IDownloadTarget() {
mTaskHandler = new AutoTaskHandler(this);
}
/**
* 设置下载器监听
*
* @param targetListener {@link OnTargetListener}
*/
public void setOnTargetListener(OnTargetListener targetListener) {
this.mTargetListener = targetListener;
}
/**
* 获取当前运行的任务数
*
* @return 当前正在执行的任务数
*/
public int getCurrentTaskNum() {
return mExecutePool.size();
}
/**
* 获取缓存任务数
*
* @return 获取缓存的任务数
*/
public int getCacheTaskNum() {
return mCachePool.size();
}
public void setFailNum(int mFailNum) {
this.mFailNum = mFailNum;
}
public void setTimeOut(long timeOut) {
this.mTimeOut = timeOut;
}
/**
* 自动处理任务停止下载失败取消下载自动下载下一个任务的操作
*/
private static class AutoTaskHandler extends Handler {
private static final String TAG = "AutoTaskHandler";
IDownloadTarget target;
public AutoTaskHandler(IDownloadTarget target) {
this.target = target;
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
DownloadEntity entity = (DownloadEntity) msg.obj;
if (entity == null) {
Log.e(TAG, "请传入下载实体DownloadEntity");
return;
}
switch (msg.what) {
case STOP:
startNextTask(entity);
break;
case CANCEL:
startNextTask(entity);
break;
case COMPLETE:
startNextTask(entity);
break;
case FAIL:
handleFailTask(entity);
break;
}
}
/**
* 处理下载任务下载失败的情形
*
* @param entity 失败实体
*/
private void handleFailTask(DownloadEntity entity) {
if (entity.getFailNum() <= target.mFailNum) {
Task task = target.getTask(entity.getDownloadUrl());
target.reTryStart(task);
} else {
startNextTask(entity);
}
}
/**
* 启动下一个任务条件任务停止取消下载任务完成
*
* @param entity 通过Handler传递的下载实体
*/
private void startNextTask(DownloadEntity entity) {
target.removeTask(entity.getDownloadUrl());
Task newTask = target.getNextTask();
if (newTask == null) {
Log.e(TAG, "没有下一任务");
return;
}
target.startTask(newTask);
}
}
}

@ -5,7 +5,6 @@ import android.content.Intent;
import android.os.Handler; import android.os.Handler;
import android.util.Log; import android.util.Log;
import com.arialyy.downloadutil.DownloadManager;
import com.arialyy.downloadutil.entity.DownloadEntity; import com.arialyy.downloadutil.entity.DownloadEntity;
import com.arialyy.downloadutil.util.IDownloadListener; import com.arialyy.downloadutil.util.IDownloadListener;
import com.arialyy.downloadutil.util.DownLoadUtil; import com.arialyy.downloadutil.util.DownLoadUtil;
@ -17,27 +16,8 @@ import java.net.HttpURLConnection;
* 下载任务类 * 下载任务类
*/ */
public class Task { public class Task {
public static final String TAG = "Task"; public static final String TAG = "Task";
/**
* 任务开始
*/
public static final int START = 1;
/**
* 任务停止
*/
public static final int STOP = 2;
/**
* 任务失败
*/
public static final int FAILE = 3;
/**
* 任务取消
*/
public static final int CANCEL = 4;
/**
* 任务完成
*/
public static final int COMPLETE = 5;
DownloadEntity downloadEntity; DownloadEntity downloadEntity;
IDownloadListener listener; IDownloadListener listener;
Handler outHandler; Handler outHandler;
@ -121,7 +101,7 @@ public class Task {
public void onStart(long startLocation) { public void onStart(long startLocation) {
super.onStart(startLocation); super.onStart(startLocation);
downloadEntity.setState(DownloadEntity.STATE_DOWNLOAD_ING); downloadEntity.setState(DownloadEntity.STATE_DOWNLOAD_ING);
sendInState2Target(START); sendInState2Target(IDownloadTarget.START);
sendIntent(DownloadManager.ACTION_START, startLocation); sendIntent(DownloadManager.ACTION_START, startLocation);
} }
@ -138,7 +118,7 @@ public class Task {
public void onStop(long stopLocation) { public void onStop(long stopLocation) {
super.onStop(stopLocation); super.onStop(stopLocation);
downloadEntity.setState(DownloadEntity.STATE_STOP); downloadEntity.setState(DownloadEntity.STATE_STOP);
sendInState2Target(STOP); sendInState2Target(IDownloadTarget.STOP);
sendIntent(DownloadManager.ACTION_STOP, stopLocation); sendIntent(DownloadManager.ACTION_STOP, stopLocation);
} }
@ -146,7 +126,7 @@ public class Task {
public void onCancel() { public void onCancel() {
super.onCancel(); super.onCancel();
downloadEntity.setState(DownloadEntity.STATE_CANCEL); downloadEntity.setState(DownloadEntity.STATE_CANCEL);
sendInState2Target(CANCEL); sendInState2Target(IDownloadTarget.CANCEL);
sendIntent(DownloadManager.ACTION_CANCEL, -1); sendIntent(DownloadManager.ACTION_CANCEL, -1);
downloadEntity.deleteData(); downloadEntity.deleteData();
} }
@ -156,7 +136,7 @@ public class Task {
super.onComplete(); super.onComplete();
downloadEntity.setState(DownloadEntity.STATE_COMPLETE); downloadEntity.setState(DownloadEntity.STATE_COMPLETE);
downloadEntity.setDownloadComplete(true); downloadEntity.setDownloadComplete(true);
sendInState2Target(COMPLETE); sendInState2Target(IDownloadTarget.COMPLETE);
sendIntent(DownloadManager.ACTION_COMPLETE, -1); sendIntent(DownloadManager.ACTION_COMPLETE, -1);
} }
@ -164,14 +144,14 @@ public class Task {
public void onFail() { public void onFail() {
super.onFail(); super.onFail();
downloadEntity.setState(DownloadEntity.STATE_FAIL); downloadEntity.setState(DownloadEntity.STATE_FAIL);
sendInState2Target(FAILE); sendInState2Target(IDownloadTarget.FAIL);
sendIntent(DownloadManager.ACTION_FAIL, -1); sendIntent(DownloadManager.ACTION_FAIL, -1);
} }
/** /**
* 将任务状态发送给下载器 * 将任务状态发送给下载器
* *
* @param state {@link Task#START} * @param state {@link IDownloadTarget#START}
*/ */
private void sendInState2Target(int state) { private void sendInState2Target(int state) {
if (outHandler != null) { if (outHandler != null) {

@ -28,4 +28,11 @@ public interface IDownloader {
*/ */
public void cancelTask(Task task); public void cancelTask(Task task);
/**
* 重试下载
*
* @param task {@link Task}
*/
public void reTryStart(Task task);
} }

@ -37,6 +37,14 @@ public interface IPool {
*/ */
public boolean removeTask(Task task); public boolean removeTask(Task task);
/**
* 通过下载链接移除下载任务
*
* @param downloadUrl 下载链接
* @return true:移除成功
*/
public boolean removeTask(String downloadUrl);
/** /**
* 池子大小 * 池子大小
* *

@ -22,7 +22,7 @@ public interface ITask {
* @param downloadUrl 下载链接 * @param downloadUrl 下载链接
* @return {@link Task} * @return {@link Task}
*/ */
public Task searchTask(String downloadUrl); public Task getTask(String downloadUrl);
/** /**
* 通过下载链接搜索下载任务 * 通过下载链接搜索下载任务
@ -31,4 +31,19 @@ public interface ITask {
* @return {@link com.arialyy.downloadutil.entity.DownloadEntity#STATE_FAIL} * @return {@link com.arialyy.downloadutil.entity.DownloadEntity#STATE_FAIL}
*/ */
public int getTaskState(String downloadUrl); public int getTaskState(String downloadUrl);
/**
* 通过下载链接删除任务
*
* @param downloadUrl 下载链接
*/
public void removeTask(String downloadUrl);
/**
* 获取缓存池的下一个任务
*
* @return 下载任务 or null
*/
public Task getNextTask();
} }

@ -1,5 +1,6 @@
package com.arialyy.downloadutil.core.pool; package com.arialyy.downloadutil.core.pool;
import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import com.arialyy.downloadutil.core.Task; import com.arialyy.downloadutil.core.Task;
@ -73,6 +74,10 @@ public class CachePool implements IPool {
@Override @Override
public Task getTask(String downloadUrl) { public Task getTask(String downloadUrl) {
synchronized (LOCK) { synchronized (LOCK) {
if (TextUtils.isEmpty(downloadUrl)) {
Log.e(TAG, "请传入有效的下载链接");
return null;
}
String key = Util.keyToHashKey(downloadUrl); String key = Util.keyToHashKey(downloadUrl);
Task task = mCacheArray.get(key); Task task = mCacheArray.get(key);
if (task != null) { if (task != null) {
@ -97,6 +102,20 @@ public class CachePool implements IPool {
} }
} }
@Override
public boolean removeTask(String downloadUrl) {
synchronized (LOCK) {
if (TextUtils.isEmpty(downloadUrl)) {
Log.e(TAG, "请传入有效的下载链接");
return false;
}
String key = Util.keyToHashKey(downloadUrl);
Task task = mCacheArray.get(key);
mCacheArray.remove(key);
return mCacheQueue.remove(task);
}
}
@Override @Override
public int size() { public int size() {
return mCacheQueue.size(); return mCacheQueue.size();

@ -1,5 +1,6 @@
package com.arialyy.downloadutil.core.pool; package com.arialyy.downloadutil.core.pool;
import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import com.arialyy.downloadutil.core.Task; import com.arialyy.downloadutil.core.Task;
@ -115,6 +116,10 @@ public class ExecutePool implements IPool {
@Override @Override
public Task getTask(String downloadUrl) { public Task getTask(String downloadUrl) {
synchronized (LOCK) { synchronized (LOCK) {
if (TextUtils.isEmpty(downloadUrl)) {
Log.e(TAG, "请传入有效的下载链接");
return null;
}
String key = Util.keyToHashKey(downloadUrl); String key = Util.keyToHashKey(downloadUrl);
Task task = mExecuteArray.get(key); Task task = mExecuteArray.get(key);
if (task != null) { if (task != null) {
@ -141,6 +146,20 @@ public class ExecutePool implements IPool {
} }
} }
@Override
public boolean removeTask(String downloadUrl) {
synchronized (LOCK) {
if (TextUtils.isEmpty(downloadUrl)) {
Log.e(TAG, "请传入有效的下载链接");
return false;
}
String key = Util.keyToHashKey(downloadUrl);
Task task = mExecuteArray.get(key);
mExecuteArray.remove(key);
return mExecuteQueue.remove(task);
}
}
@Override @Override
public int size() { public int size() {
return mExecuteQueue.size(); return mExecuteQueue.size();

@ -46,6 +46,15 @@ public class DownloadEntity extends DbEntity implements Parcelable, Cloneable {
private int state = STATE_WAIT; private int state = STATE_WAIT;
private boolean isDownloadComplete = false; //是否下载完成 private boolean isDownloadComplete = false; //是否下载完成
private long currentProgress = 0; //当前下载进度 private long currentProgress = 0; //当前下载进度
private int failNum = 0;
public int getFailNum() {
return failNum;
}
public void setFailNum(int failNum) {
this.failNum = failNum;
}
public String getDownloadUrl() { public String getDownloadUrl() {
return downloadUrl; return downloadUrl;
@ -126,6 +135,7 @@ public class DownloadEntity extends DbEntity implements Parcelable, Cloneable {
dest.writeInt(this.state); dest.writeInt(this.state);
dest.writeByte(this.isDownloadComplete ? (byte) 1 : (byte) 0); dest.writeByte(this.isDownloadComplete ? (byte) 1 : (byte) 0);
dest.writeLong(this.currentProgress); dest.writeLong(this.currentProgress);
dest.writeInt(this.failNum);
} }
protected DownloadEntity(Parcel in) { protected DownloadEntity(Parcel in) {
@ -136,6 +146,7 @@ public class DownloadEntity extends DbEntity implements Parcelable, Cloneable {
this.state = in.readInt(); this.state = in.readInt();
this.isDownloadComplete = in.readByte() != 0; this.isDownloadComplete = in.readByte() != 0;
this.currentProgress = in.readLong(); this.currentProgress = in.readLong();
this.failNum = in.readInt();
} }
public static final Creator<DownloadEntity> CREATOR = new Creator<DownloadEntity>() { public static final Creator<DownloadEntity> CREATOR = new Creator<DownloadEntity>() {
@ -149,4 +160,18 @@ public class DownloadEntity extends DbEntity implements Parcelable, Cloneable {
return new DownloadEntity[size]; return new DownloadEntity[size];
} }
}; };
@Override
public String toString() {
return "DownloadEntity{" +
"downloadUrl='" + downloadUrl + '\'' +
", downloadPath='" + downloadPath + '\'' +
", completeTime=" + completeTime +
", fileSize=" + fileSize +
", state=" + state +
", isDownloadComplete=" + isDownloadComplete +
", currentProgress=" + currentProgress +
", failNum=" + failNum +
'}';
}
} }
Loading…
Cancel
Save