优化Scheduler代码
This commit is contained in:
@ -56,6 +56,8 @@ import org.xml.sax.SAXException;
|
||||
private static final String DOWNLOAD = "_download";
|
||||
private static final String UPLOAD = "_upload";
|
||||
private static final Object LOCK = new Object();
|
||||
public static final String DOWNLOAD_TEMP_DIR = "/Aria/temp/download/";
|
||||
public static final String UPLOAD_TEMP_DIR = "/Aria/temp/upload/";
|
||||
@SuppressLint("StaticFieldLeak") private static volatile AriaManager INSTANCE = null;
|
||||
private Map<String, IReceiver> mReceivers = new HashMap<>();
|
||||
public static Context APP;
|
||||
@ -247,6 +249,7 @@ import org.xml.sax.SAXException;
|
||||
*/
|
||||
private void initConfig() {
|
||||
File xmlFile = new File(APP.getFilesDir().getPath() + Configuration.XML_FILE);
|
||||
File tempDir = new File(APP.getFilesDir().getPath() + "/temp");
|
||||
if (!xmlFile.exists()) {
|
||||
loadConfig();
|
||||
} else {
|
||||
@ -261,6 +264,11 @@ import org.xml.sax.SAXException;
|
||||
}
|
||||
mDConfig = Configuration.DownloadConfig.getInstance();
|
||||
mUConfig = Configuration.UploadConfig.getInstance();
|
||||
if (tempDir.exists()) {
|
||||
File newDir = new File(APP.getFilesDir().getPath() + DOWNLOAD_TEMP_DIR);
|
||||
newDir.mkdirs();
|
||||
tempDir.renameTo(newDir);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -25,7 +25,7 @@ import org.xml.sax.helpers.DefaultHandler;
|
||||
* Created by lyy on 2017/5/22.
|
||||
* 读取配置文件
|
||||
*/
|
||||
public class ConfigHelper extends DefaultHandler {
|
||||
class ConfigHelper extends DefaultHandler {
|
||||
private final String TAG = "ConfigHelper";
|
||||
|
||||
private boolean isDownloadConfig = false, isUploadConfig;
|
||||
|
@ -129,6 +129,8 @@ public class DownloadTarget extends AbsTarget<DownloadEntity, DownloadTaskEntity
|
||||
|
||||
/**
|
||||
* 设置文件名
|
||||
*
|
||||
* @deprecated {@link #setFileName(String)}
|
||||
*/
|
||||
@Deprecated public DownloadTarget setDownloadName(@NonNull String downloadName) {
|
||||
if (TextUtils.isEmpty(downloadName)) {
|
||||
@ -138,6 +140,17 @@ public class DownloadTarget extends AbsTarget<DownloadEntity, DownloadTaskEntity
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置文件名
|
||||
*/
|
||||
public DownloadTarget setFileName(@NonNull String fileName) {
|
||||
if (TextUtils.isEmpty(fileName)) {
|
||||
throw new IllegalArgumentException("文件名不能为null");
|
||||
}
|
||||
entity.setFileName(fileName);
|
||||
return this;
|
||||
}
|
||||
|
||||
private DownloadEntity getDownloadEntity() {
|
||||
return entity;
|
||||
}
|
||||
|
@ -61,7 +61,6 @@ class DownloadUtil implements IDownloadUtil, Runnable {
|
||||
private DownloadStateConstance CONSTANCE;
|
||||
|
||||
DownloadUtil(Context context, DownloadTaskEntity entity, IDownloadListener downloadListener) {
|
||||
CheckUtil.checkTaskEntity(entity);
|
||||
mDownloadEntity = entity.downloadEntity;
|
||||
mContext = context.getApplicationContext();
|
||||
mDownloadTaskEntity = entity;
|
||||
@ -77,7 +76,7 @@ class DownloadUtil implements IDownloadUtil, Runnable {
|
||||
mDownloadFile = new File(mDownloadTaskEntity.downloadEntity.getDownloadPath());
|
||||
//读取已完成的线程数
|
||||
mConfigFile = new File(
|
||||
mContext.getFilesDir().getPath() + "/temp/" + mDownloadFile.getName() + ".properties");
|
||||
mContext.getFilesDir().getPath() + AriaManager.DOWNLOAD_TEMP_DIR + mDownloadFile.getName() + ".properties");
|
||||
try {
|
||||
if (!mConfigFile.exists()) { //记录文件被删除,则重新下载
|
||||
handleNewTask();
|
||||
|
@ -114,7 +114,7 @@ final class SingleThreadTask implements Runnable {
|
||||
if (mConfigEntity.isSupportBreakpoint) {
|
||||
Log.i(TAG,
|
||||
"任务【" + mConfigEntity.TEMP_FILE.getName() + "】线程【" + mConfigEntity.THREAD_ID + "】下载完毕");
|
||||
writeConfig(mConfigEntity.TEMP_FILE.getName() + "_state_" + mConfigEntity.THREAD_ID, 1);
|
||||
writeConfig(1);
|
||||
mListener.onChildComplete(mConfigEntity.END_LOCATION);
|
||||
CONSTANCE.COMPLETE_THREAD_NUM++;
|
||||
if (CONSTANCE.isComplete()) {
|
||||
@ -131,12 +131,11 @@ final class SingleThreadTask implements Runnable {
|
||||
mListener.onComplete();
|
||||
}
|
||||
} catch (MalformedURLException e) {
|
||||
failDownload(mConfigEntity, mChildCurrentLocation, "下载链接异常", e);
|
||||
failDownload(mChildCurrentLocation, "下载链接异常", e);
|
||||
} catch (IOException e) {
|
||||
failDownload(mConfigEntity, mChildCurrentLocation, "下载失败【" + mConfigEntity.DOWNLOAD_URL + "】",
|
||||
e);
|
||||
failDownload(mChildCurrentLocation, "下载失败【" + mConfigEntity.DOWNLOAD_URL + "】", e);
|
||||
} catch (Exception e) {
|
||||
failDownload(mConfigEntity, mChildCurrentLocation, "获取流失败", e);
|
||||
failDownload(mChildCurrentLocation, "获取流失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -152,8 +151,7 @@ final class SingleThreadTask implements Runnable {
|
||||
+ mConfigEntity.THREAD_ID
|
||||
+ "_stop, stop location ==> "
|
||||
+ mChildCurrentLocation);
|
||||
writeConfig(mConfigEntity.TEMP_FILE.getName() + "_record_" + mConfigEntity.THREAD_ID,
|
||||
mChildCurrentLocation);
|
||||
writeConfig(mChildCurrentLocation);
|
||||
if (CONSTANCE.isStop()) {
|
||||
Log.d(TAG, "++++++++++++++++ onStop +++++++++++++++++");
|
||||
CONSTANCE.isDownloading = false;
|
||||
@ -212,19 +210,17 @@ final class SingleThreadTask implements Runnable {
|
||||
/**
|
||||
* 下载失败
|
||||
*/
|
||||
private void failDownload(DownloadUtil.ConfigEntity dEntity, long currentLocation, String msg,
|
||||
Exception ex) {
|
||||
private void failDownload(long currentLocation, String msg, Exception ex) {
|
||||
synchronized (LOCK) {
|
||||
try {
|
||||
CONSTANCE.FAIL_NUM++;
|
||||
CONSTANCE.isDownloading = false;
|
||||
CONSTANCE.isStop = true;
|
||||
if (ex != null) {
|
||||
Log.e(TAG, CommonUtil.getPrintException(ex));
|
||||
Log.e(TAG, msg + "\n" + CommonUtil.getPrintException(ex));
|
||||
}
|
||||
if (mConfigEntity.isSupportBreakpoint) {
|
||||
writeConfig(dEntity.TEMP_FILE.getName() + "_record_" + dEntity.THREAD_ID,
|
||||
currentLocation);
|
||||
writeConfig(currentLocation);
|
||||
if (CONSTANCE.isFail()) {
|
||||
Log.d(TAG, "++++++++++++++++ onFail +++++++++++++++++");
|
||||
mListener.onFail();
|
||||
@ -242,8 +238,9 @@ final class SingleThreadTask implements Runnable {
|
||||
/**
|
||||
* 将记录写入到配置文件
|
||||
*/
|
||||
private void writeConfig(String key, long record) throws IOException {
|
||||
private void writeConfig(long record) throws IOException {
|
||||
if (record > 0) {
|
||||
String key = mConfigEntity.TEMP_FILE.getName() + "_record_" + mConfigEntity.THREAD_ID;
|
||||
File configFile = new File(mConfigFPath);
|
||||
Properties pro = CommonUtil.loadConfig(configFile);
|
||||
pro.setProperty(key, String.valueOf(record));
|
||||
|
@ -0,0 +1,190 @@
|
||||
/*
|
||||
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.arialyy.aria.core.scheduler;
|
||||
|
||||
import android.os.CountDownTimer;
|
||||
import android.os.Message;
|
||||
import android.util.Log;
|
||||
import com.arialyy.aria.core.AriaManager;
|
||||
import com.arialyy.aria.core.inf.AbsEntity;
|
||||
import com.arialyy.aria.core.inf.AbsTaskEntity;
|
||||
import com.arialyy.aria.core.inf.IEntity;
|
||||
import com.arialyy.aria.core.inf.ITask;
|
||||
import com.arialyy.aria.core.queue.ITaskQueue;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* Created by AriaL on 2017/6/4.
|
||||
*/
|
||||
public abstract class AbsSchedulers<TASK_ENTITY extends AbsTaskEntity, ENTITY extends AbsEntity, TASK extends ITask<ENTITY>, QUEUE extends ITaskQueue<TASK, TASK_ENTITY, ENTITY>>
|
||||
implements ISchedulers<TASK> {
|
||||
private static final String TAG = "AbsSchedulers";
|
||||
|
||||
protected QUEUE mQueue;
|
||||
|
||||
private Map<String, IDownloadSchedulerListener<TASK>> mSchedulerListeners =
|
||||
new ConcurrentHashMap<>();
|
||||
|
||||
@Override
|
||||
public void addSchedulerListener(String targetName, ISchedulerListener<TASK> schedulerListener) {
|
||||
mSchedulerListeners.put(targetName, (IDownloadSchedulerListener<TASK>) schedulerListener);
|
||||
}
|
||||
|
||||
@Override public void removeSchedulerListener(String targetName,
|
||||
ISchedulerListener<TASK> schedulerListener) {
|
||||
//该内存泄露解决方案:http://stackoverflow.com/questions/14585829/how-safe-is-to-delete-already-removed-concurrenthashmap-element
|
||||
for (Iterator<Map.Entry<String, IDownloadSchedulerListener<TASK>>> iter =
|
||||
mSchedulerListeners.entrySet().iterator(); iter.hasNext(); ) {
|
||||
Map.Entry<String, IDownloadSchedulerListener<TASK>> entry = iter.next();
|
||||
if (entry.getKey().equals(targetName)) iter.remove();
|
||||
}
|
||||
}
|
||||
|
||||
@Override public boolean handleMessage(Message msg) {
|
||||
TASK task = (TASK) msg.obj;
|
||||
if (task == null) {
|
||||
Log.e(TAG, "请传入下载任务");
|
||||
return true;
|
||||
}
|
||||
callback(msg.what, task);
|
||||
ENTITY entity = task.getEntity();
|
||||
switch (msg.what) {
|
||||
case STOP:
|
||||
case CANCEL:
|
||||
mQueue.removeTask(entity);
|
||||
if (mQueue.executePoolSize() < AriaManager.getInstance(AriaManager.APP)
|
||||
.getUploadConfig()
|
||||
.getMaxTaskNum()) {
|
||||
startNextTask();
|
||||
}
|
||||
break;
|
||||
case COMPLETE:
|
||||
mQueue.removeTask(entity);
|
||||
startNextTask();
|
||||
break;
|
||||
case FAIL:
|
||||
handleFailTask(task);
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 回调
|
||||
*
|
||||
* @param state 状态
|
||||
*/
|
||||
private void callback(int state, TASK task) {
|
||||
if (mSchedulerListeners.size() > 0) {
|
||||
Set<String> keys = mSchedulerListeners.keySet();
|
||||
for (String key : keys) {
|
||||
callback(state, task, mSchedulerListeners.get(key));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void callback(int state, TASK task, IDownloadSchedulerListener<TASK> listener) {
|
||||
if (listener != null) {
|
||||
if (task == null) {
|
||||
Log.e(TAG, "TASK 为null,回调失败");
|
||||
return;
|
||||
}
|
||||
switch (state) {
|
||||
case PRE:
|
||||
listener.onPre(task);
|
||||
break;
|
||||
case POST_PRE:
|
||||
listener.onTaskPre(task);
|
||||
break;
|
||||
case RUNNING:
|
||||
listener.onTaskRunning(task);
|
||||
break;
|
||||
case START:
|
||||
listener.onTaskStart(task);
|
||||
break;
|
||||
case STOP:
|
||||
listener.onTaskStop(task);
|
||||
break;
|
||||
case RESUME:
|
||||
listener.onTaskResume(task);
|
||||
break;
|
||||
case CANCEL:
|
||||
listener.onTaskCancel(task);
|
||||
break;
|
||||
case COMPLETE:
|
||||
listener.onTaskComplete(task);
|
||||
break;
|
||||
case FAIL:
|
||||
listener.onTaskFail(task);
|
||||
break;
|
||||
case SUPPORT_BREAK_POINT:
|
||||
listener.onNoSupportBreakPoint(task);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理下载任务下载失败的情形
|
||||
*
|
||||
* @param task 下载任务
|
||||
*/
|
||||
private void handleFailTask(final TASK task) {
|
||||
final long interval =
|
||||
AriaManager.getInstance(AriaManager.APP).getUploadConfig().getReTryInterval();
|
||||
final int reTryNum = AriaManager.getInstance(AriaManager.APP).getUploadConfig().getReTryNum();
|
||||
|
||||
CountDownTimer timer = new CountDownTimer(interval, 1000) {
|
||||
@Override public void onTick(long millisUntilFinished) {
|
||||
|
||||
}
|
||||
|
||||
@Override public void onFinish() {
|
||||
ENTITY entity = task.getEntity();
|
||||
if (entity.getFailNum() < reTryNum) {
|
||||
TASK task = mQueue.getTask(entity);
|
||||
mQueue.reTryStart(task);
|
||||
try {
|
||||
Thread.sleep(interval);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
mQueue.removeTask(entity);
|
||||
startNextTask();
|
||||
}
|
||||
}
|
||||
};
|
||||
timer.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* 启动下一个任务,条件:任务停止,取消下载,任务完成
|
||||
*/
|
||||
private void startNextTask() {
|
||||
TASK newTask = mQueue.getNextTask();
|
||||
if (newTask == null) {
|
||||
Log.w(TAG, "没有下一任务");
|
||||
return;
|
||||
}
|
||||
if (newTask.getEntity().getState() == IEntity.STATE_WAIT) {
|
||||
mQueue.startTask(newTask);
|
||||
}
|
||||
}
|
||||
}
|
@ -16,35 +16,22 @@
|
||||
|
||||
package com.arialyy.aria.core.scheduler;
|
||||
|
||||
import android.os.CountDownTimer;
|
||||
import android.os.Message;
|
||||
import android.util.Log;
|
||||
import com.arialyy.aria.core.AriaManager;
|
||||
import com.arialyy.aria.core.download.DownloadTaskEntity;
|
||||
import com.arialyy.aria.core.queue.DownloadTaskQueue;
|
||||
import com.arialyy.aria.core.download.DownloadEntity;
|
||||
import com.arialyy.aria.core.download.DownloadTask;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* Created by lyy on 2016/8/16.
|
||||
* 任务下载器,提供抽象的方法供具体的实现类操作
|
||||
*/
|
||||
public class DownloadSchedulers implements ISchedulers<DownloadTask> {
|
||||
public class DownloadSchedulers
|
||||
extends AbsSchedulers<DownloadTaskEntity, DownloadEntity, DownloadTask, DownloadTaskQueue> {
|
||||
|
||||
private static final String TAG = "DownloadSchedulers";
|
||||
private static final Object LOCK = new Object();
|
||||
private static volatile DownloadSchedulers INSTANCE = null;
|
||||
|
||||
/**
|
||||
* 下载器任务监听
|
||||
*/
|
||||
private Map<String, IDownloadSchedulerListener<DownloadTask>> mSchedulerListeners =
|
||||
new ConcurrentHashMap<>();
|
||||
private DownloadTaskQueue mQueue;
|
||||
|
||||
private DownloadSchedulers() {
|
||||
mQueue = DownloadTaskQueue.getInstance();
|
||||
}
|
||||
@ -57,156 +44,4 @@ public class DownloadSchedulers implements ISchedulers<DownloadTask> {
|
||||
}
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
@Override public void addSchedulerListener(String targetName,
|
||||
ISchedulerListener<DownloadTask> schedulerListener) {
|
||||
mSchedulerListeners.put(targetName,
|
||||
(IDownloadSchedulerListener<DownloadTask>) schedulerListener);
|
||||
}
|
||||
|
||||
@Override public void removeSchedulerListener(String targetName,
|
||||
ISchedulerListener<DownloadTask> schedulerListener) {
|
||||
//该内存溢出解决方案:http://stackoverflow.com/questions/14585829/how-safe-is-to-delete-already-removed-concurrenthashmap-element
|
||||
for (Iterator<Map.Entry<String, IDownloadSchedulerListener<DownloadTask>>> iter =
|
||||
mSchedulerListeners.entrySet().iterator(); iter.hasNext(); ) {
|
||||
Map.Entry<String, IDownloadSchedulerListener<DownloadTask>> entry = iter.next();
|
||||
if (entry.getKey().equals(targetName)) iter.remove();
|
||||
}
|
||||
}
|
||||
|
||||
@Override public boolean handleMessage(Message msg) {
|
||||
DownloadTask task = (DownloadTask) msg.obj;
|
||||
if (task == null) {
|
||||
Log.e(TAG, "请传入下载任务");
|
||||
return true;
|
||||
}
|
||||
callback(msg.what, task);
|
||||
DownloadEntity entity = task.getDownloadEntity();
|
||||
switch (msg.what) {
|
||||
case STOP:
|
||||
case CANCEL:
|
||||
mQueue.removeTask(entity);
|
||||
if (mQueue.executePoolSize() < AriaManager.getInstance(AriaManager.APP)
|
||||
.getUploadConfig()
|
||||
.getMaxTaskNum()) {
|
||||
startNextTask();
|
||||
}
|
||||
break;
|
||||
case COMPLETE:
|
||||
mQueue.removeTask(entity);
|
||||
startNextTask();
|
||||
break;
|
||||
case FAIL:
|
||||
handleFailTask(task);
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 回调
|
||||
*
|
||||
* @param state 状态
|
||||
*/
|
||||
private void callback(int state, DownloadTask task) {
|
||||
if (mSchedulerListeners.size() > 0) {
|
||||
//if (!TextUtils.isEmpty(task.getTargetName())) {
|
||||
// callback(state, task, mSchedulerListeners.get(task.getTargetName()));
|
||||
//}
|
||||
Set<String> keys = mSchedulerListeners.keySet();
|
||||
for (String key : keys) {
|
||||
callback(state, task, mSchedulerListeners.get(key));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void callback(int state, DownloadTask task,
|
||||
IDownloadSchedulerListener<DownloadTask> listener) {
|
||||
if (listener != null) {
|
||||
if (task == null) {
|
||||
Log.e(TAG, "TASK 为null,回调失败");
|
||||
return;
|
||||
}
|
||||
switch (state) {
|
||||
case PRE:
|
||||
listener.onPre(task);
|
||||
break;
|
||||
case POST_PRE:
|
||||
listener.onTaskPre(task);
|
||||
break;
|
||||
case RUNNING:
|
||||
listener.onTaskRunning(task);
|
||||
break;
|
||||
case START:
|
||||
listener.onTaskStart(task);
|
||||
break;
|
||||
case STOP:
|
||||
listener.onTaskStop(task);
|
||||
break;
|
||||
case RESUME:
|
||||
listener.onTaskResume(task);
|
||||
break;
|
||||
case CANCEL:
|
||||
listener.onTaskCancel(task);
|
||||
break;
|
||||
case COMPLETE:
|
||||
listener.onTaskComplete(task);
|
||||
break;
|
||||
case FAIL:
|
||||
listener.onTaskFail(task);
|
||||
break;
|
||||
case SUPPORT_BREAK_POINT:
|
||||
listener.onNoSupportBreakPoint(task);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理下载任务下载失败的情形
|
||||
*
|
||||
* @param task 下载任务
|
||||
*/
|
||||
private void handleFailTask(final DownloadTask task) {
|
||||
final long interval =
|
||||
AriaManager.getInstance(AriaManager.APP).getUploadConfig().getReTryInterval();
|
||||
final int reTryNum = AriaManager.getInstance(AriaManager.APP).getUploadConfig().getReTryNum();
|
||||
|
||||
CountDownTimer timer = new CountDownTimer(interval, 1000) {
|
||||
@Override public void onTick(long millisUntilFinished) {
|
||||
|
||||
}
|
||||
|
||||
@Override public void onFinish() {
|
||||
DownloadEntity entity = task.getDownloadEntity();
|
||||
if (entity.getFailNum() < reTryNum) {
|
||||
DownloadTask task = mQueue.getTask(entity);
|
||||
mQueue.reTryStart(task);
|
||||
try {
|
||||
Thread.sleep(interval);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
mQueue.removeTask(entity);
|
||||
startNextTask();
|
||||
}
|
||||
}
|
||||
};
|
||||
timer.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* 启动下一个任务,条件:任务停止,取消下载,任务完成
|
||||
*/
|
||||
private void startNextTask() {
|
||||
DownloadTask newTask = mQueue.getNextTask();
|
||||
if (newTask == null) {
|
||||
Log.w(TAG, "没有下一任务");
|
||||
return;
|
||||
}
|
||||
if (newTask.getDownloadEntity().getState() == DownloadEntity.STATE_WAIT) {
|
||||
mQueue.startTask(newTask);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -15,30 +15,20 @@
|
||||
*/
|
||||
package com.arialyy.aria.core.scheduler;
|
||||
|
||||
import android.os.CountDownTimer;
|
||||
import android.os.Message;
|
||||
import android.util.Log;
|
||||
import com.arialyy.aria.core.AriaManager;
|
||||
import com.arialyy.aria.core.inf.IEntity;
|
||||
import com.arialyy.aria.core.queue.UploadTaskQueue;
|
||||
import com.arialyy.aria.core.upload.UploadEntity;
|
||||
import com.arialyy.aria.core.upload.UploadTask;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import com.arialyy.aria.core.upload.UploadTaskEntity;
|
||||
|
||||
/**
|
||||
* Created by lyy on 2017/2/27.
|
||||
* 上传任务调度器
|
||||
*/
|
||||
public class UploadSchedulers implements ISchedulers<UploadTask> {
|
||||
public class UploadSchedulers
|
||||
extends AbsSchedulers<UploadTaskEntity, UploadEntity, UploadTask, UploadTaskQueue> {
|
||||
private static final String TAG = "UploadSchedulers";
|
||||
private static final Object LOCK = new Object();
|
||||
private static volatile UploadSchedulers INSTANCE = null;
|
||||
private Map<String, ISchedulerListener<UploadTask>> mSchedulerListeners =
|
||||
new ConcurrentHashMap<>();
|
||||
private UploadTaskQueue mQueue;
|
||||
|
||||
private UploadSchedulers() {
|
||||
mQueue = UploadTaskQueue.getInstance();
|
||||
@ -53,141 +43,4 @@ public class UploadSchedulers implements ISchedulers<UploadTask> {
|
||||
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
@Override public void addSchedulerListener(String targetName,
|
||||
ISchedulerListener<UploadTask> schedulerListener) {
|
||||
mSchedulerListeners.put(targetName, schedulerListener);
|
||||
}
|
||||
|
||||
@Override public void removeSchedulerListener(String targetName,
|
||||
ISchedulerListener<UploadTask> schedulerListener) {
|
||||
for (Iterator<Map.Entry<String, ISchedulerListener<UploadTask>>> iter =
|
||||
mSchedulerListeners.entrySet().iterator(); iter.hasNext(); ) {
|
||||
Map.Entry<String, ISchedulerListener<UploadTask>> entry = iter.next();
|
||||
if (entry.getKey().equals(targetName)) iter.remove();
|
||||
}
|
||||
}
|
||||
|
||||
private void handleFailTask(final UploadTask task) {
|
||||
final long interval =
|
||||
AriaManager.getInstance(AriaManager.APP).getUploadConfig().getReTryInterval();
|
||||
final int reTryNum = AriaManager.getInstance(AriaManager.APP).getUploadConfig().getReTryNum();
|
||||
CountDownTimer timer = new CountDownTimer(interval, 1000) {
|
||||
@Override public void onTick(long millisUntilFinished) {
|
||||
|
||||
}
|
||||
|
||||
@Override public void onFinish() {
|
||||
UploadEntity entity = task.getEntity();
|
||||
if (entity.getFailNum() <= reTryNum) {
|
||||
UploadTask task = mQueue.getTask(entity);
|
||||
mQueue.reTryStart(task);
|
||||
try {
|
||||
Thread.sleep(interval);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
mQueue.removeTask(entity);
|
||||
startNextTask();
|
||||
}
|
||||
}
|
||||
};
|
||||
timer.start();
|
||||
}
|
||||
|
||||
private void startNextTask() {
|
||||
UploadTask newTask = mQueue.getNextTask();
|
||||
if (newTask == null) {
|
||||
Log.w(TAG, "没有下一任务");
|
||||
return;
|
||||
}
|
||||
if (newTask.getEntity().getState() == IEntity.STATE_WAIT) {
|
||||
mQueue.startTask(newTask);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 回调
|
||||
*
|
||||
* @param state 状态
|
||||
*/
|
||||
private void callback(int state, UploadTask task) {
|
||||
if (mSchedulerListeners.size() > 0) {
|
||||
//if (!TextUtils.isEmpty(task.getTargetName())) {
|
||||
// callback(state, task, mSchedulerListeners.get(task.getTargetName()));
|
||||
//}
|
||||
Set<String> keys = mSchedulerListeners.keySet();
|
||||
for (String key : keys) {
|
||||
callback(state, task, mSchedulerListeners.get(key));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void callback(int state, UploadTask task, ISchedulerListener<UploadTask> listener) {
|
||||
if (listener != null) {
|
||||
if (task == null) {
|
||||
Log.e(TAG, "TASK 为null,回调失败");
|
||||
return;
|
||||
}
|
||||
switch (state) {
|
||||
case PRE:
|
||||
listener.onPre(task);
|
||||
break;
|
||||
case POST_PRE:
|
||||
listener.onTaskPre(task);
|
||||
break;
|
||||
case RUNNING:
|
||||
listener.onTaskRunning(task);
|
||||
break;
|
||||
case START:
|
||||
listener.onTaskStart(task);
|
||||
break;
|
||||
case STOP:
|
||||
listener.onTaskStop(task);
|
||||
break;
|
||||
case RESUME:
|
||||
listener.onTaskResume(task);
|
||||
break;
|
||||
case CANCEL:
|
||||
listener.onTaskCancel(task);
|
||||
break;
|
||||
case COMPLETE:
|
||||
listener.onTaskComplete(task);
|
||||
break;
|
||||
case FAIL:
|
||||
listener.onTaskFail(task);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override public boolean handleMessage(Message msg) {
|
||||
UploadTask task = (UploadTask) msg.obj;
|
||||
if (task == null) {
|
||||
Log.e(TAG, "请传入上传任务");
|
||||
return true;
|
||||
}
|
||||
callback(msg.what, task);
|
||||
UploadEntity entity = task.getEntity();
|
||||
switch (msg.what) {
|
||||
case STOP:
|
||||
case CANCEL:
|
||||
mQueue.removeTask(entity);
|
||||
if (mQueue.executePoolSize() < AriaManager.getInstance(AriaManager.APP)
|
||||
.getUploadConfig()
|
||||
.getMaxTaskNum()) {
|
||||
startNextTask();
|
||||
}
|
||||
break;
|
||||
case COMPLETE:
|
||||
mQueue.removeTask(entity);
|
||||
startNextTask();
|
||||
break;
|
||||
case FAIL:
|
||||
handleFailTask(task);
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -497,7 +497,7 @@ final class SqlHelper extends SQLiteOpenHelper {
|
||||
}
|
||||
|
||||
private static void close(SQLiteDatabase db) {
|
||||
//if (db != null && db.isOpen()) db.close();
|
||||
if (db != null && db.isOpen()) db.close();
|
||||
}
|
||||
|
||||
private static SQLiteDatabase checkDb(SQLiteDatabase db) {
|
||||
|
Reference in New Issue
Block a user