loader 优化

This commit is contained in:
laoyuyu
2019-12-28 13:18:20 +08:00
parent c9eb57132b
commit 1e237d795d
52 changed files with 1005 additions and 691 deletions

View File

@@ -1,44 +0,0 @@
/*
* 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.common;
import com.arialyy.aria.core.inf.IRecordHandlerAdapter;
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
import com.arialyy.aria.util.CommonUtil;
/**
* @Author lyy
* @Date 2019-09-19
*/
public abstract class AbsRecordHandlerAdapter implements IRecordHandlerAdapter {
private AbsTaskWrapper mWrapper;
protected String TAG = CommonUtil.getClassName(getClass());
@Override public void onPre() {
}
public AbsRecordHandlerAdapter(AbsTaskWrapper wrapper) {
mWrapper = wrapper;
}
public AbsTaskWrapper getWrapper() {
return mWrapper;
}
protected AbsNormalEntity getEntity() {
return (AbsNormalEntity) getWrapper().getEntity();
}
}

View File

@@ -18,8 +18,8 @@ package com.arialyy.aria.core.common;
import com.arialyy.aria.core.TaskRecord;
import com.arialyy.aria.core.ThreadRecord;
import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.inf.IRecordHandler;
import com.arialyy.aria.core.inf.IRecordHandlerAdapter;
import com.arialyy.aria.core.loader.ILoaderVisitor;
import com.arialyy.aria.core.loader.IRecordHandler;
import com.arialyy.aria.core.upload.UploadEntity;
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
import com.arialyy.aria.core.wrapper.ITaskWrapper;
@@ -38,22 +38,29 @@ import java.util.Set;
/**
* 处理任务记录,分配线程区间
*/
public class RecordHandler implements IRecordHandler {
private final String TAG = "RecordHandler";
public abstract class RecordHandler implements IRecordHandler {
protected final String TAG = CommonUtil.getClassName(this);
@Deprecated private File mConfigFile;
private TaskRecord mTaskRecord;
private AbsTaskWrapper mTaskWrapper;
private AbsNormalEntity mEntity;
private IRecordHandlerAdapter mAdapter;
public RecordHandler(AbsTaskWrapper wrapper) {
mTaskWrapper = wrapper;
mEntity = (AbsNormalEntity) mTaskWrapper.getEntity();
}
public void setAdapter(IRecordHandlerAdapter mAdapter) {
this.mAdapter = mAdapter;
public AbsTaskWrapper getWrapper() {
return mTaskWrapper;
}
public AbsNormalEntity getEntity() {
return mEntity;
}
@Override public void onPre() {
}
/**
@@ -70,10 +77,10 @@ public class RecordHandler implements IRecordHandler {
if (mConfigFile.exists()) {
convertDb();
} else {
mAdapter.onPre();
onPre();
mTaskRecord = DbDataHelper.getTaskRecord(getFilePath(), mEntity.getTaskType());
if (mTaskRecord == null) {
if (!new File(getFilePath()).exists()){
if (!new File(getFilePath()).exists()) {
FileUtil.createFile(getFilePath());
}
initRecord(true);
@@ -83,14 +90,14 @@ public class RecordHandler implements IRecordHandler {
ALog.w(TAG, String.format("文件【%s】不存在重新分配线程区间", mTaskRecord.filePath));
DbEntity.deleteData(ThreadRecord.class, "taskKey=?", mTaskRecord.filePath);
mTaskRecord.threadRecords.clear();
mTaskRecord.threadNum = mAdapter.initTaskThreadNum();
mTaskRecord.threadNum = initTaskThreadNum();
initRecord(false);
} else if (mTaskRecord.threadRecords == null || mTaskRecord.threadRecords.isEmpty()) {
mTaskRecord.threadNum = mAdapter.initTaskThreadNum();
mTaskRecord.threadNum = initTaskThreadNum();
initRecord(false);
}
}
mAdapter.handlerTaskRecord(mTaskRecord);
handlerTaskRecord(mTaskRecord);
}
saveRecord();
return mTaskRecord;
@@ -127,7 +134,7 @@ public class RecordHandler implements IRecordHandler {
return;
}
mTaskWrapper.setNewTask(false);
mTaskRecord = mAdapter.createTaskRecord(threadNum);
mTaskRecord = createTaskRecord(threadNum);
mTaskRecord.isBlock = false;
File tempFile = new File(getFilePath());
for (int i = 0; i < threadNum; i++) {
@@ -158,7 +165,7 @@ public class RecordHandler implements IRecordHandler {
*/
private void initRecord(boolean newRecord) {
if (newRecord) {
mTaskRecord = mAdapter.createTaskRecord(mAdapter.initTaskThreadNum());
mTaskRecord = createTaskRecord(initTaskThreadNum());
}
mTaskWrapper.setNewTask(true);
int requestType = mTaskWrapper.getRequestType();
@@ -169,7 +176,7 @@ public class RecordHandler implements IRecordHandler {
// 处理线程区间记录
for (int i = 0; i < mTaskRecord.threadNum; i++) {
long startL = i * blockSize, endL = (i + 1) * blockSize;
ThreadRecord tr = mAdapter.createThreadRecord(mTaskRecord, i, startL, endL);
ThreadRecord tr = createThreadRecord(mTaskRecord, i, startL, endL);
mTaskRecord.threadRecords.add(tr);
}
}
@@ -198,4 +205,23 @@ public class RecordHandler implements IRecordHandler {
return ((UploadEntity) mTaskWrapper.getEntity()).getFilePath();
}
}
@Override public void accept(ILoaderVisitor visitor) {
visitor.addComponent(this);
}
@Override public boolean checkTaskCompleted() {
if (mTaskRecord == null
|| mTaskRecord.threadRecords == null
|| mTaskRecord.threadRecords.isEmpty()) {
return false;
}
int completeNum = 0;
for (ThreadRecord tr : mTaskRecord.threadRecords) {
if (tr.isComplete) {
completeNum++;
}
}
return completeNum != 0 && completeNum == mTaskRecord.threadNum;
}
}

View File

@@ -17,7 +17,7 @@ package com.arialyy.aria.core.common;
import com.arialyy.aria.core.TaskRecord;
import com.arialyy.aria.core.ThreadRecord;
import com.arialyy.aria.core.inf.IRecordHandler;
import com.arialyy.aria.core.loader.IRecordHandler;
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.BufferedRandomAccessFile;

View File

@@ -62,13 +62,13 @@ public class XMLReader extends DefaultHandler {
String value = attributes.getValue("value");
switch (qName) {
case "threadNum": // 线程数
case "getCreatedThreadNum": // 线程数
int threadNum = checkInt(value) ? Integer.parseInt(value) : 3;
if (threadNum < 1) {
ALog.w(TAG, "下载线程数不能小于 1");
threadNum = 1;
}
setField("threadNum", threadNum, ConfigType.DOWNLOAD);
setField("getCreatedThreadNum", threadNum, ConfigType.DOWNLOAD);
break;
case "maxTaskNum": //最大任务书
int maxTaskNum = checkInt(value) ? Integer.parseInt(value) : 2;

View File

@@ -37,7 +37,7 @@ import java.util.concurrent.TimeUnit;
* Created by AriaL on 2017/6/30.
* 任务组核心逻辑
*/
public abstract class AbsGroupUtil implements IUtil, Runnable {
public abstract class AbsGroupLoaderUtil implements IUtil, Runnable {
protected final String TAG = CommonUtil.getClassName(getClass());
private long mCurrentLocation = 0;
@@ -52,7 +52,7 @@ public abstract class AbsGroupUtil implements IUtil, Runnable {
private DGTaskWrapper mGTWrapper;
private GroupRunState mState;
protected AbsGroupUtil(AbsTaskWrapper groupWrapper, IEventListener listener) {
protected AbsGroupLoaderUtil(AbsTaskWrapper groupWrapper, IEventListener listener) {
mListener = (IDGroupListener) listener;
mGTWrapper = (DGTaskWrapper) groupWrapper;
mUpdateInterval = Configuration.getInstance().downloadCfg.getUpdateInterval();

View File

@@ -30,7 +30,7 @@ import java.util.concurrent.TimeUnit;
/**
* 组合任务子任务调度器,用于调度任务的开始、停止、失败、完成等情况
* 该调度器生命周期和{@link AbsGroupUtil}生命周期一致
* 该调度器生命周期和{@link AbsGroupLoaderUtil}生命周期一致
*/
class SimpleSchedulers implements ISchedulers {
private static final String TAG = "SimpleSchedulers";

View File

@@ -26,7 +26,7 @@ import java.util.Map;
import java.util.Set;
/**
* 组合任务队列,该队列生命周期和{@link AbsGroupUtil}生命周期一致
* 组合任务队列,该队列生命周期和{@link AbsGroupLoaderUtil}生命周期一致
*/
class SimpleSubQueue implements ISubQueue<AbsSubDLoadUtil> {
private static final String TAG = "SimpleSubQueue";

View File

@@ -16,11 +16,14 @@
package com.arialyy.aria.core.inf;
import android.os.Handler;
import android.os.Looper;
import com.arialyy.aria.core.TaskRecord;
import com.arialyy.aria.core.loader.ILoaderComponent;
/**
* 线程任务状态
*/
public interface IThreadState extends Handler.Callback {
public interface IThreadState extends ILoaderComponent {
int STATE_STOP = 0x01;
int STATE_FAIL = 0x02;
int STATE_CANCEL = 0x03;
@@ -50,4 +53,14 @@ public interface IThreadState extends Handler.Callback {
* @return 任务当前进度
*/
long getCurrentProgress();
/**
* 设置消息循环体
*/
void setLooper(TaskRecord taskRecord, Looper looper);
/**
* 创建handler 回调
*/
Handler.Callback getHandlerCallback();
}

View File

@@ -19,7 +19,7 @@ import android.os.Handler;
import com.arialyy.aria.core.download.DTaskWrapper;
import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.inf.IEntity;
import com.arialyy.aria.core.inf.IRecordHandler;
import com.arialyy.aria.core.loader.IRecordHandler;
import com.arialyy.aria.core.inf.TaskSchedulerType;
import com.arialyy.aria.core.task.AbsTask;
import com.arialyy.aria.util.CommonUtil;

View File

@@ -17,7 +17,7 @@ package com.arialyy.aria.core.listener;
import android.os.Handler;
import com.arialyy.aria.core.inf.IEntity;
import com.arialyy.aria.core.inf.IRecordHandler;
import com.arialyy.aria.core.loader.IRecordHandler;
import com.arialyy.aria.core.inf.TaskSchedulerType;
import com.arialyy.aria.core.task.AbsTask;
import com.arialyy.aria.core.upload.UTaskWrapper;

View File

@@ -21,7 +21,7 @@ import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.download.DownloadGroupEntity;
import com.arialyy.aria.core.group.GroupSendParams;
import com.arialyy.aria.core.inf.IEntity;
import com.arialyy.aria.core.inf.IRecordHandler;
import com.arialyy.aria.core.loader.IRecordHandler;
import com.arialyy.aria.core.inf.TaskSchedulerType;
import com.arialyy.aria.core.task.AbsTask;
import com.arialyy.aria.core.task.DownloadGroupTask;

View File

@@ -16,9 +16,7 @@
package com.arialyy.aria.core.loader;
import android.os.Looper;
import android.util.SparseArray;
import com.arialyy.aria.core.TaskRecord;
import com.arialyy.aria.core.inf.IRecordHandler;
import com.arialyy.aria.core.inf.IThreadState;
import com.arialyy.aria.core.listener.IEventListener;
import com.arialyy.aria.core.manager.ThreadTaskManager;
@@ -27,20 +25,27 @@ import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.CommonUtil;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* Created by AriaL on 2017/7/1.
* 控制线程任务状态,如:开始,停止,取消,重试
* 任务执行器,用于处理任务的开始,停止
* 流程:
* 1、获取任务记录
* 2、创建任务状态管理器用于管理任务的状态
* 3、创建文件信息获取器获取文件信息根据文件信息执行任务
* 4、创建线程任务执行下载、上传操作
*/
public abstract class AbsLoader implements Runnable {
public abstract class AbsLoader implements ILoaderVisitor, ILoader {
protected final String TAG;
protected IEventListener mListener;
protected AbsTaskWrapper mTaskWrapper;
protected File mTempFile;
private SparseArray<IThreadTask> mTask = new SparseArray<>();
private List<IThreadTask> mTask = new ArrayList<>();
private ScheduledThreadPoolExecutor mTimer;
/**
@@ -48,20 +53,23 @@ public abstract class AbsLoader implements Runnable {
*/
private long mUpdateInterval = 1000;
protected TaskRecord mRecord;
private IThreadState mStateManager;
private boolean isCancel = false, isStop = false;
private boolean isRuning = false;
private Looper mLooper;
protected AbsLoader(IEventListener listener, AbsTaskWrapper wrapper) {
protected IRecordHandler mRecordHandler;
protected IThreadState mStateManager;
protected IInfoTask mInfoTask;
protected IThreadTaskBuilder mTTBuilder;
protected AbsLoader(AbsTaskWrapper wrapper, IEventListener listener) {
mListener = listener;
mTaskWrapper = wrapper;
TAG = CommonUtil.getClassName(getClass());
}
protected abstract IThreadState createStateManager(Looper looper);
/**
* 处理任务
* 启动线程任务
*/
protected abstract void handleTask();
@@ -70,11 +78,6 @@ public abstract class AbsLoader implements Runnable {
*/
public abstract long getFileSize();
/**
* 获取当前任务位置
*/
public abstract long getCurrentLocation();
public IThreadState getStateManager() {
return mStateManager;
}
@@ -83,7 +86,7 @@ public abstract class AbsLoader implements Runnable {
return mTaskWrapper.getKey();
}
public SparseArray<IThreadTask> getTaskList() {
public List<IThreadTask> getTaskList() {
return mTask;
}
@@ -94,16 +97,20 @@ public abstract class AbsLoader implements Runnable {
closeTimer();
if (mTask != null && mTask.size() != 0) {
for (int i = 0; i < mTask.size(); i++) {
mTask.valueAt(i).breakTask();
mTask.get(i).breakTask();
}
mTask.clear();
}
}
/**
* 任务记录工具
*/
protected abstract IRecordHandler getRecordHandler(AbsTaskWrapper wrapper);
@Override public void run() {
checkComponent();
if (isRunning()) {
ALog.d(TAG, String.format("任务【%s】正在执行启动任务失败", mTaskWrapper.getKey()));
return;
}
startFlow();
}
/**
* 开始流程
@@ -114,21 +121,18 @@ public abstract class AbsLoader implements Runnable {
}
isRuning = true;
resetState();
mRecord = getRecordHandler(mTaskWrapper).getRecord();
Looper.prepare();
Looper looper = Looper.myLooper();
mStateManager = createStateManager(looper);
onPostPre();
handleTask();
startTimer();
Looper.loop();
}
@Override public void run() {
if (isRunning()) {
return;
@Override public Looper getLooper() {
if (mLooper == null) {
Looper.prepare();
mLooper = Looper.myLooper();
}
startFlow();
return mLooper;
}
/**
@@ -212,7 +216,7 @@ public abstract class AbsLoader implements Runnable {
isCancel = true;
onCancel();
for (int i = 0; i < mTask.size(); i++) {
IThreadTask task = mTask.valueAt(i);
IThreadTask task = mTask.get(i);
if (task != null && !task.isThreadComplete()) {
task.cancel();
}
@@ -245,7 +249,7 @@ public abstract class AbsLoader implements Runnable {
isStop = true;
onStop();
for (int i = 0; i < mTask.size(); i++) {
IThreadTask task = mTask.valueAt(i);
IThreadTask task = mTask.get(i);
if (task != null && !task.isThreadComplete()) {
task.stop();
}
@@ -253,7 +257,7 @@ public abstract class AbsLoader implements Runnable {
ThreadTaskManager.getInstance().removeTaskThread(mTaskWrapper.getKey());
onPostStop();
onDestroy();
mListener.onStop(getCurrentLocation());
mListener.onStop(getCurrentProgress());
}
/**
@@ -270,17 +274,6 @@ public abstract class AbsLoader implements Runnable {
}
/**
* 直接调用的时候会自动启动线程执行
*/
public synchronized void start() {
if (isRunning()) {
ALog.d(TAG, String.format("任务【%s】正在执行启动任务失败", mTaskWrapper.getKey()));
return;
}
new Thread(this).start();
}
/**
* 重试任务
*/
@@ -303,4 +296,22 @@ public abstract class AbsLoader implements Runnable {
}
return false;
}
/**
* 检查组件: {@link #mRecordHandler}、{@link #mInfoTask}、{@link #mStateManager}、{@link #mTTBuilder}
*/
private void checkComponent() {
if (mRecordHandler == null) {
throw new NullPointerException("任务记录组件为空");
}
if (mInfoTask == null) {
throw new NullPointerException(("文件信息组件为空"));
}
if (mStateManager == null) {
throw new NullPointerException("任务状态管理组件为空");
}
if (mTTBuilder == null) {
throw new NullPointerException("线程任务组件为空");
}
}
}

View File

@@ -29,19 +29,25 @@ import com.arialyy.aria.util.CommonUtil;
public abstract class AbsNormalLoaderUtil implements IUtil {
protected String TAG = CommonUtil.getClassName(getClass());
private IEventListener mListener;
private AbsLoader mLoader;
protected AbsLoader mLoader;
private AbsTaskWrapper mTaskWrapper;
private boolean isStop = false, isCancel = false;
protected AbsNormalLoaderUtil(AbsTaskWrapper wrapper, IEventListener listener) {
mTaskWrapper = wrapper;
mListener = listener;
mLoader = createLoader();
mLoader = getLoader();
}
public AbsLoader getLoader() {
return mLoader;
}
/**
* 获取加载器
*/
public abstract AbsLoader getLoader();
/**
* 获取构造器
*/
public abstract LoaderStructure getLoaderStructure();
@Override public String getKey() {
return mTaskWrapper.getKey();
@@ -55,7 +61,7 @@ public abstract class AbsNormalLoaderUtil implements IUtil {
* 获取当前下载位置
*/
@Override public long getCurrentLocation() {
return mLoader.getCurrentLocation();
return mLoader.getCurrentProgress();
}
@Override public boolean isRunning() {
@@ -105,10 +111,10 @@ public abstract class AbsNormalLoaderUtil implements IUtil {
//} else {
// mDownloader.create();
//}
Runnable runnable = createInfoThread();
if (runnable != null) {
new Thread(runnable).start();
}
getLoaderStructure();
new Thread(mLoader).start();
onStart();
}
@@ -139,14 +145,4 @@ public abstract class AbsNormalLoaderUtil implements IUtil {
public AbsTaskWrapper getTaskWrapper() {
return mTaskWrapper;
}
/**
* 创建加载器的适配器
*/
protected abstract AbsLoader createLoader();
/**
* 通过链接类型创建不同的获取文件信息的线程
*/
protected abstract Runnable createInfoThread();
}

View File

@@ -0,0 +1,185 @@
package com.arialyy.aria.core.loader;
import android.os.Handler;
import android.os.Looper;
import com.arialyy.aria.core.TaskRecord;
import com.arialyy.aria.core.ThreadRecord;
import com.arialyy.aria.core.common.AbsNormalEntity;
import com.arialyy.aria.core.common.SubThreadConfig;
import com.arialyy.aria.core.download.DGTaskWrapper;
import com.arialyy.aria.core.inf.IThreadState;
import com.arialyy.aria.core.task.IThreadTask;
import com.arialyy.aria.core.task.IThreadTaskAdapter;
import com.arialyy.aria.core.task.ThreadTask;
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.CommonUtil;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
public abstract class AbsNormalTTBuilder implements IThreadTaskBuilder {
protected String TAG = CommonUtil.getClassName(this);
private Handler mStateHandler;
private AbsTaskWrapper mWrapper;
private TaskRecord mRecord;
private int mTotalThreadNum;
private File mTempFile;
private int mStartThreadNum;
public AbsNormalTTBuilder(AbsTaskWrapper wrapper) {
if (wrapper instanceof DGTaskWrapper) {
throw new AssertionError("NormalTTBuilder 不适用于组合任务");
}
mWrapper = wrapper;
mTempFile = new File(((AbsNormalEntity) wrapper.getEntity()).getFilePath());
}
protected File getTempFile(){
return mTempFile;
}
protected AbsNormalEntity getEntity() {
return (AbsNormalEntity) mWrapper.getEntity();
}
/**
* 创建线程任务适配器
*/
public abstract IThreadTaskAdapter getAdapter(SubThreadConfig config);
/**
* 处理新任务
*
* @param record 任务记录
* @param totalThreadNum 任务的线程总数
* @return {@code true}创建新任务成功
*/
public abstract boolean handleNewTask(TaskRecord record, int totalThreadNum);
/**
* 创建线程任务
*/
private IThreadTask createThreadTask(SubThreadConfig config) {
ThreadTask task = new ThreadTask(config);
task.setAdapter(getAdapter(config));
return task;
}
/**
* 启动断点任务时,创建单线程任务
*
* @param record 线程记录
* @param startNum 启动的线程数
*/
private IThreadTask createSingThreadTask(ThreadRecord record, int startNum) {
SubThreadConfig config = new SubThreadConfig();
config.url = getEntity().isRedirect() ? getEntity().getRedirectUrl() : getEntity().getUrl();
config.tempFile =
mRecord.isBlock ? new File(
String.format(IRecordHandler.SUB_PATH, mTempFile.getPath(), record.threadId))
: mTempFile;
config.isBlock = mRecord.isBlock;
config.startThreadNum = startNum;
config.taskWrapper = mWrapper;
config.record = record;
config.stateHandler = mStateHandler;
return createThreadTask(config);
}
/**
* 处理不支持断点的任务
*/
private List<IThreadTask> handleNoSupportBP() {
List<IThreadTask> list = new ArrayList<>();
mStartThreadNum = 1;
IThreadTask task = createSingThreadTask(mRecord.threadRecords.get(0), 1);
if (task == null) {
ALog.e(TAG, "创建线程任务失败");
return null;
}
list.add(task);
return list;
}
/**
* 处理支持断点的任务
*/
private List<IThreadTask> handleBreakpoint() {
long fileLength = getEntity().getFileSize();
long blockSize = fileLength / mTotalThreadNum;
long currentProgress = 0;
List<IThreadTask> threadTasks = new ArrayList<>();
mRecord.fileLength = fileLength;
if (mWrapper.isNewTask() && !handleNewTask(mRecord, mTotalThreadNum)) {
ALog.e(TAG, "初始化线程任务失败");
return null;
}
for (ThreadRecord tr : mRecord.threadRecords) {
if (!tr.isComplete) {
mStartThreadNum++;
}
}
for (int i = 0; i < mTotalThreadNum; i++) {
long startL = i * blockSize, endL = (i + 1) * blockSize;
ThreadRecord tr = mRecord.threadRecords.get(i);
if (tr.isComplete) {//该线程已经完成
currentProgress += endL - startL;
ALog.d(TAG, String.format("任务【%s】线程__%s__已完成", mWrapper.getKey(), i));
mStateHandler.obtainMessage(IThreadState.STATE_COMPLETE).sendToTarget();
continue;
}
//如果有记录,则恢复任务
long r = tr.startLocation;
//记录的位置需要在线程区间中
if (startL < r && r <= (i == (mTotalThreadNum - 1) ? fileLength : endL)) {
currentProgress += r - startL;
}
ALog.d(TAG, String.format("任务【%s】线程__%s__恢复任务", getEntity().getFileName(), i));
IThreadTask task = createSingThreadTask(tr, mStartThreadNum);
if (task == null) {
ALog.e(TAG, "创建线程任务失败");
return null;
}
threadTasks.add(task);
}
if (currentProgress != 0 && currentProgress != getEntity().getCurrentProgress()) {
ALog.d(TAG, String.format("进度修正,当前进度:%s", currentProgress));
getEntity().setCurrentProgress(currentProgress);
}
//mStateManager.updateProgress(currentProgress);
return threadTasks;
}
private List<IThreadTask> handleTask() {
if (mWrapper.isSupportBP()) {
return handleBreakpoint();
}else {
return handleNoSupportBP();
}
}
@Override public List<IThreadTask> buildThreadTask(TaskRecord record, Looper looper,
IThreadState stateManager) {
mRecord = record;
mStateHandler = new Handler(looper, stateManager.getHandlerCallback());
mTotalThreadNum = mRecord.threadNum;
return handleTask();
}
@Override public int getCreatedThreadNum() {
return mStartThreadNum;
}
@Override public void accept(ILoaderVisitor visitor) {
visitor.addComponent(this);
}
}

View File

@@ -13,24 +13,40 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.arialyy.aria.core.inf;
package com.arialyy.aria.core.loader;
import com.arialyy.aria.core.common.CompleteInfo;
import com.arialyy.aria.core.common.AbsEntity;
import com.arialyy.aria.core.common.CompleteInfo;
import com.arialyy.aria.exception.BaseException;
public interface OnFileInfoCallback {
/**
* 处理完成
*
* @param info 一些回调的信息
*/
void onComplete(String key, CompleteInfo info);
/**
* 任务信息采集
*/
public interface IInfoTask extends ILoaderComponent {
/**
* 请求失败
*
* @param e 错误信息
* 执行任务
*/
void onFail(AbsEntity entity, BaseException e, boolean needRetry);
}
void run();
/**
* 设置回调
*/
void setCallback(Callback callback);
interface Callback {
/**
* 处理完成
*
* @param info 一些回调的信息
*/
void onSucceed(String key, CompleteInfo info);
/**
* 请求失败
*
* @param e 错误信息
*/
void onFail(AbsEntity entity, BaseException e, boolean needRetry);
}
}

View File

@@ -15,15 +15,24 @@
*/
package com.arialyy.aria.core.loader;
public interface ILoader {
import android.os.Looper;
void start();
public interface ILoader extends Runnable{
//void start();
void stop();
void isBreak();
/**
* 任务是否被中断(停止,取消)
*
* @return true 任务中断false 任务没有中断
*/
boolean isBreak();
String getKey();
long getCurrentProgress();
Looper getLooper();
}

View File

@@ -16,7 +16,6 @@
package com.arialyy.aria.core.loader;
import com.arialyy.aria.core.TaskRecord;
import com.arialyy.aria.core.inf.IRecordHandler;
import com.arialyy.aria.core.task.IThreadTask;
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
import com.arialyy.aria.core.common.SubThreadConfig;

View File

@@ -15,33 +15,11 @@
*/
package com.arialyy.aria.core.loader;
public class LoaderIntercept implements ILoaderInterceptor, ILoader {
/**
* 加载器部件
*/
public interface ILoaderComponent {
void accept(ILoaderVisitor visitor);
@Override public ILoader intercept(Chain chain) {
return this;
}
@Override public void start() {
}
@Override public void stop() {
}
@Override public void isBreak() {
}
@Override public String getKey() {
return null;
}
@Override public long getCurrentProgress() {
return 0;
}
}

View File

@@ -15,27 +15,30 @@
*/
package com.arialyy.aria.core.loader;
import com.arialyy.aria.core.TaskRecord;
import com.arialyy.aria.core.listener.IEventListener;
import com.arialyy.aria.core.wrapper.ITaskWrapper;
import com.arialyy.aria.core.inf.IThreadState;
/**
* 拦截器
* 加载器访问者
*/
public interface ILoaderInterceptor {
public interface ILoaderVisitor {
ILoader intercept(Chain chain);
/**
* 处理任务记录
*/
void addComponent(IRecordHandler recordHandler);
interface Chain {
/**
* 处理任务的文件信息
*/
void addComponent(IInfoTask infoTask);
void updateRecord(TaskRecord record);
/**
* 线程状态
*/
void addComponent(IThreadState threadState);
TaskRecord getRecord();
IEventListener getListener();
ITaskWrapper getWrapper();
ILoader proceed();
}
/**
* 构造线程任务
*/
void addComponent(IThreadTaskBuilder builder);
}

View File

@@ -13,18 +13,38 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.arialyy.aria.core.inf;
package com.arialyy.aria.core.loader;
import com.arialyy.aria.core.TaskRecord;
import com.arialyy.aria.core.ThreadRecord;
/**
* 任务记录处理适配器
*
* @Author lyy
* @Date 2019-09-19
* @Date 2019-09-18
*/
public interface IRecordHandlerAdapter {
public interface IRecordHandler extends ILoaderComponent {
int TYPE_DOWNLOAD = 1;
int TYPE_UPLOAD = 2;
int TYPE_M3U8_VOD = 3;
int TYPE_M3U8_LIVE = 4;
String STATE = "_state_";
String RECORD = "_record_";
/**
* 小于1m的文件不启用多线程
*/
long SUB_LEN = 1024 * 1024;
/**
* 分块文件路径
*/
String SUB_PATH = "%s.%s.part";
/**
* 获取任务记录
*/
TaskRecord getRecord();
/**
* 记录处理前的操作可用来删除任务记录
@@ -57,4 +77,11 @@ public interface IRecordHandlerAdapter {
* @return 新任务的线程数
*/
int initTaskThreadNum();
/**
* 检查任务是否已完成
*
* @return true 任务已完成
*/
boolean checkTaskCompleted();
}

View File

@@ -13,35 +13,26 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.arialyy.aria.core.inf;
package com.arialyy.aria.core.loader;
import android.os.Looper;
import com.arialyy.aria.core.TaskRecord;
import com.arialyy.aria.core.inf.IThreadState;
import com.arialyy.aria.core.task.IThreadTask;
import java.util.List;
/**
* @Author lyy
* @Date 2019-09-18
* 线程任务构造器
*/
public interface IRecordHandler {
int TYPE_DOWNLOAD = 1;
int TYPE_UPLOAD = 2;
int TYPE_M3U8_VOD = 3;
int TYPE_M3U8_LIVE = 4;
String STATE = "_state_";
String RECORD = "_record_";
/**
* 小于1m的文件不启用多线程
*/
long SUB_LEN = 1024 * 1024;
public interface IThreadTaskBuilder extends ILoaderComponent {
/**
* 分块文件路径
* 构造线程任务
*/
String SUB_PATH = "%s.%s.part";
List<IThreadTask> buildThreadTask(TaskRecord record, Looper looper, IThreadState stateManager);
/**
* 获取任务记录
* 获取创建的线程任务数需要先调用{@link #buildThreadTask(TaskRecord, Looper, IThreadState)}方法才能获取创建的线程任务数
*/
TaskRecord getRecord();
int getCreatedThreadNum();
}

View File

@@ -1,75 +0,0 @@
/*
* 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.loader;
import com.arialyy.aria.core.TaskRecord;
import com.arialyy.aria.core.listener.IEventListener;
import com.arialyy.aria.core.wrapper.ITaskWrapper;
import java.util.List;
/**
* 责任链
*/
public final class LoaderChain implements ILoaderInterceptor.Chain {
private ITaskWrapper wrapper;
private IEventListener listener;
private TaskRecord taskRecord;
private int index;
private List<ILoaderInterceptor> interceptors;
public LoaderChain(List<ILoaderInterceptor> interceptors, ITaskWrapper wrapper,
IEventListener listener, TaskRecord taskRecord,
int index) {
this.interceptors = interceptors;
this.wrapper = wrapper;
this.listener = listener;
this.taskRecord = taskRecord;
this.index = index;
}
@Override public void updateRecord(TaskRecord record) {
this.taskRecord = record;
}
@Override public TaskRecord getRecord() {
return taskRecord;
}
@Override public IEventListener getListener() {
return listener;
}
@Override public ITaskWrapper getWrapper() {
return wrapper;
}
@Override public ILoader proceed() {
int index = this.index + 1;
if (index >= interceptors.size()) {
throw new AssertionError();
}
LoaderChain next = new LoaderChain(interceptors, wrapper, listener, taskRecord, index);
ILoaderInterceptor interceptor = interceptors.get(index);
ILoader loader = interceptor.intercept(next);
if (loader == null) {
throw new NullPointerException("Loader为空");
}
return loader;
}
}

View File

@@ -15,25 +15,31 @@
*/
package com.arialyy.aria.core.loader;
import com.arialyy.aria.core.common.RecordHandler;
import com.arialyy.aria.core.inf.IRecordHandlerAdapter;
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
import com.arialyy.aria.core.inf.IThreadState;
import java.util.ArrayList;
import java.util.List;
/**
* 任务记录拦截器用于处理任务记录
*/
public final class RecordInterceptor implements ILoaderInterceptor {
private IRecordHandlerAdapter adapter;
public class LoaderStructure {
private List<ILoaderComponent> parts = new ArrayList<>();
public RecordInterceptor(IRecordHandlerAdapter adapter) {
this.adapter = adapter;
public void accept(ILoaderVisitor visitor) {
for (ILoaderComponent part : parts) {
part.accept(visitor);
}
}
@Override public ILoader intercept(Chain chain) {
RecordHandler recordHandler = new RecordHandler((AbsTaskWrapper) chain.getWrapper());
recordHandler.setAdapter(adapter);
chain.updateRecord(recordHandler.getRecord());
return chain.proceed();
/**
* 将组件加入到集合必须添加以下集合
* 1 {@link IRecordHandler}
* 2 {@link IInfoTask}
* 3 {@link IThreadState}
* 4 {@link IThreadTaskBuilder}
*
* @param component 待添加的组件
*/
public LoaderStructure addComponent(ILoaderComponent component) {
parts.add(component);
return this;
}
}

View File

@@ -15,20 +15,17 @@
*/
package com.arialyy.aria.core.loader;
import android.os.Handler;
import android.os.Looper;
import com.arialyy.aria.core.ThreadRecord;
import com.arialyy.aria.core.common.AbsEntity;
import com.arialyy.aria.core.common.AbsNormalEntity;
import com.arialyy.aria.core.common.SubThreadConfig;
import com.arialyy.aria.core.common.CompleteInfo;
import com.arialyy.aria.core.event.EventMsgUtil;
import com.arialyy.aria.core.inf.IRecordHandler;
import com.arialyy.aria.core.inf.IThreadState;
import com.arialyy.aria.core.listener.BaseDListener;
import com.arialyy.aria.core.listener.IDLoadListener;
import com.arialyy.aria.core.listener.IEventListener;
import com.arialyy.aria.core.manager.ThreadTaskManager;
import com.arialyy.aria.core.task.IThreadTask;
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
import com.arialyy.aria.exception.BaseException;
import com.arialyy.aria.util.ALog;
import java.io.File;
@@ -36,23 +33,15 @@ import java.io.File;
* 单文件
*/
public class NormalLoader extends AbsLoader {
private ThreadStateManager mStateManager;
private Handler mStateHandler;
protected int mTotalThreadNum; //总线程数
private int mStartThreadNum; //启动的线程数
private ILoaderAdapter mAdapter;
public NormalLoader(IEventListener listener, AbsTaskWrapper wrapper) {
super(listener, wrapper);
public NormalLoader(AbsTaskWrapper wrapper, IEventListener listener) {
super(wrapper, listener);
mTempFile = new File(getEntity().getFilePath());
EventMsgUtil.getDefault().register(this);
setUpdateInterval(wrapper.getConfig().getUpdateInterval());
}
public void setAdapter(ILoaderAdapter adapter) {
mAdapter = adapter;
}
public AbsNormalEntity getEntity() {
return (AbsNormalEntity) mTaskWrapper.getEntity();
}
@@ -61,24 +50,15 @@ public class NormalLoader extends AbsLoader {
return getEntity().getFileSize();
}
@Override public long getCurrentLocation() {
return isRunning() ? mStateManager.getCurrentProgress() : getEntity().getCurrentProgress();
}
@Override protected IRecordHandler getRecordHandler(AbsTaskWrapper wrapper) {
return mAdapter.recordHandler(wrapper);
}
/**
* 设置最大下载/上传速度
* 设置最大下载/上传速度AbsFtpInfoThread
*
* @param maxSpeed 单位为kb
*/
protected void setMaxSpeed(int maxSpeed) {
for (int i = 0; i < getTaskList().size(); i++) {
IThreadTask task = getTaskList().valueAt(i);
if (task != null && mStartThreadNum > 0) {
task.setMaxSpeed(maxSpeed / mStartThreadNum);
for (IThreadTask threadTask : getTaskList()) {
if (threadTask != null && mStartThreadNum > 0) {
threadTask.setMaxSpeed(maxSpeed / mStartThreadNum);
}
}
}
@@ -90,11 +70,6 @@ public class NormalLoader extends AbsLoader {
@Override protected void onPostPre() {
super.onPostPre();
if (mAdapter == null) {
throw new NullPointerException("请使用adapter设置适配器");
}
mTotalThreadNum = mRecord.threadNum;
if (mListener instanceof IDLoadListener) {
((IDLoadListener) mListener).onPostPre(getEntity().getFileSize());
}
@@ -114,126 +89,63 @@ public class NormalLoader extends AbsLoader {
}
}
@Override protected IThreadState createStateManager(Looper looper) {
mStateManager = new ThreadStateManager(looper, mRecord, mListener);
mStateHandler = new Handler(looper, mStateManager);
return mStateManager;
}
@Override protected void handleTask() {
if (mTaskWrapper.isSupportBP()) {
handleBreakpoint();
} else {
handleNoSupportBP();
}
}
/**
* 启动断点任务时,创建单线程任务
*
* @param record 线程记录
* @param startNum 启动的线程数
*/
private IThreadTask createSingThreadTask(ThreadRecord record, int startNum) {
SubThreadConfig config = new SubThreadConfig();
config.url = getEntity().isRedirect() ? getEntity().getRedirectUrl() : getEntity().getUrl();
config.tempFile =
mRecord.isBlock ? new File(
String.format(IRecordHandler.SUB_PATH, mTempFile.getPath(), record.threadId))
: mTempFile;
config.isBlock = mRecord.isBlock;
config.startThreadNum = startNum;
config.taskWrapper = mTaskWrapper;
config.record = record;
config.stateHandler = mStateHandler;
return mAdapter.createThreadTask(config);
}
private void handleBreakpoint() {
long fileLength = getEntity().getFileSize();
long blockSize = fileLength / mTotalThreadNum;
long currentProgress = 0;
mRecord.fileLength = fileLength;
if (mTaskWrapper.isNewTask() && !mAdapter.handleNewTask(mRecord, mTotalThreadNum)) {
closeTimer();
mListener.onFail(false, null);
return;
}
for (ThreadRecord tr : mRecord.threadRecords) {
if (!tr.isComplete) {
mStartThreadNum++;
}
}
for (int i = 0; i < mTotalThreadNum; i++) {
long startL = i * blockSize, endL = (i + 1) * blockSize;
ThreadRecord tr = mRecord.threadRecords.get(i);
if (tr.isComplete) {//该线程已经完成
currentProgress += endL - startL;
ALog.d(TAG, String.format("任务【%s】线程__%s__已完成", mTaskWrapper.getKey(), i));
mStateHandler.obtainMessage(IThreadState.STATE_COMPLETE).sendToTarget();
if (mStateManager.isComplete()) {
mRecord.deleteData();
mListener.onComplete();
return;
}
continue;
}
//如果有记录,则恢复任务
long r = tr.startLocation;
//记录的位置需要在线程区间中
if (startL < r && r <= (i == (mTotalThreadNum - 1) ? fileLength : endL)) {
currentProgress += r - startL;
}
ALog.d(TAG, String.format("任务【%s】线程__%s__恢复任务", getEntity().getFileName(), i));
IThreadTask task = createSingThreadTask(tr, mStartThreadNum);
if (task == null) return;
getTaskList().put(tr.threadId, task);
}
if (currentProgress != 0 && currentProgress != getEntity().getCurrentProgress()) {
ALog.d(TAG, String.format("进度修正,当前进度:%s", currentProgress));
getEntity().setCurrentProgress(currentProgress);
}
mStateManager.updateProgress(currentProgress);
startThreadTask();
}
/**
* 启动单线程任务
*/
private void startThreadTask() {
@Override
public void handleTask() {
if (isBreak()) {
return;
}
mStateManager.setLooper(mRecord, getLooper());
mInfoTask.run();
}
private void startThreadTask() {
getTaskList().addAll(mTTBuilder.buildThreadTask(mRecord, getLooper(), mStateManager));
mStartThreadNum = mTTBuilder.getCreatedThreadNum();
if (mStateManager.getCurrentProgress() > 0) {
mListener.onResume(mStateManager.getCurrentProgress());
} else {
mListener.onStart(mStateManager.getCurrentProgress());
}
for (int i = 0; i < getTaskList().size(); i++) {
ThreadTaskManager.getInstance().startThread(mTaskWrapper.getKey(), getTaskList().valueAt(i));
for (IThreadTask threadTask : getTaskList()) {
ThreadTaskManager.getInstance().startThread(mTaskWrapper.getKey(), threadTask);
}
}
/**
* 处理不支持断点的任务
*/
private void handleNoSupportBP() {
if (mListener instanceof BaseDListener) {
((BaseDListener) mListener).supportBreakpoint(false);
}
mStartThreadNum = 1;
@Override public long getCurrentProgress() {
return isRunning() ? mStateManager.getCurrentProgress() : getEntity().getCurrentProgress();
}
IThreadTask task = createSingThreadTask(mRecord.threadRecords.get(0), 1);
if (task == null) return;
getTaskList().put(0, task);
ThreadTaskManager.getInstance().startThread(mTaskWrapper.getKey(), task);
mListener.onStart(0);
@Override public void addComponent(IRecordHandler recordHandler) {
mRecordHandler = recordHandler;
mRecord = mRecordHandler.getRecord();
if (recordHandler.checkTaskCompleted()) {
mRecord.deleteData();
mListener.onComplete();
}
}
@Override public void addComponent(IInfoTask infoTask) {
mInfoTask = infoTask;
infoTask.setCallback(new IInfoTask.Callback() {
@Override public void onSucceed(String key, CompleteInfo info) {
startThreadTask();
}
@Override public void onFail(AbsEntity entity, BaseException e, boolean needRetry) {
mListener.onFail(needRetry, e);
}
});
}
@Override public void addComponent(IThreadState threadState) {
mStateManager = threadState;
}
@Override public void addComponent(IThreadTaskBuilder builder) {
mTTBuilder = builder;
}
}

View File

@@ -16,10 +16,10 @@
package com.arialyy.aria.core.loader;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import com.arialyy.aria.core.TaskRecord;
import com.arialyy.aria.core.inf.IRecordHandler;
import com.arialyy.aria.core.inf.IThreadState;
import com.arialyy.aria.core.listener.IEventListener;
import com.arialyy.aria.exception.BaseException;
@@ -49,16 +49,85 @@ public class ThreadStateManager implements IThreadState {
private Looper mLooper;
/**
* @param taskRecord 任务记录
* @param listener 任务事件
*/
ThreadStateManager(Looper looper, TaskRecord taskRecord, IEventListener listener) {
mLooper = looper;
mTaskRecord = taskRecord;
mThreadNum = mTaskRecord.threadNum;
public ThreadStateManager(IEventListener listener) {
mListener = listener;
}
@Override public void setLooper(TaskRecord taskRecord, Looper looper) {
mTaskRecord = taskRecord;
mThreadNum = mTaskRecord.threadNum;
mLooper = looper;
}
private void checkLooper(){
if (mTaskRecord == null){
throw new NullPointerException("任务记录为空");
}
if (mLooper == null){
throw new NullPointerException("Looper为空");
}
}
private Handler.Callback callback = new Handler.Callback() {
@Override public boolean handleMessage(Message msg) {
checkLooper();
switch (msg.what) {
case STATE_STOP:
mStopNum++;
if (isStop()) {
quitLooper();
}
break;
case STATE_CANCEL:
mCancelNum++;
if (isCancel()) {
quitLooper();
}
break;
case STATE_FAIL:
mFailNum++;
if (isFail()) {
Bundle b = msg.getData();
mListener.onFail(b.getBoolean(KEY_RETRY, false),
(BaseException) b.getSerializable(KEY_ERROR_INFO));
quitLooper();
}
break;
case STATE_COMPLETE:
mCompleteNum++;
if (isComplete()) {
ALog.d(TAG, "isComplete, completeNum = " + mCompleteNum);
if (mTaskRecord.isBlock) {
if (mergeFile()) {
mListener.onComplete();
} else {
mListener.onFail(false, null);
}
} else {
mListener.onComplete();
}
quitLooper();
}
break;
case STATE_RUNNING:
if (msg.obj instanceof Long) {
mProgress += (long) msg.obj;
}
break;
case STATE_UPDATE_PROGRESS:
if (msg.obj == null) {
mProgress = updateBlockProgress();
} else if (msg.obj instanceof Long) {
mProgress = (long) msg.obj;
}
break;
}
return false;
}
};
/**
* 不要使用handle更新启动线程的进度因为有延迟
*/
@@ -66,61 +135,6 @@ public class ThreadStateManager implements IThreadState {
mProgress = curProgress;
}
@Override public boolean handleMessage(Message msg) {
switch (msg.what) {
case STATE_STOP:
mStopNum++;
if (isStop()) {
quitLooper();
}
break;
case STATE_CANCEL:
mCancelNum++;
if (isCancel()) {
quitLooper();
}
break;
case STATE_FAIL:
mFailNum++;
if (isFail()) {
Bundle b = msg.getData();
mListener.onFail(b.getBoolean(KEY_RETRY, false),
(BaseException) b.getSerializable(KEY_ERROR_INFO));
quitLooper();
}
break;
case STATE_COMPLETE:
mCompleteNum++;
if (isComplete()) {
ALog.d(TAG, "isComplete, completeNum = " + mCompleteNum);
if (mTaskRecord.isBlock) {
if (mergeFile()) {
mListener.onComplete();
} else {
mListener.onFail(false, null);
}
} else {
mListener.onComplete();
}
quitLooper();
}
break;
case STATE_RUNNING:
if (msg.obj instanceof Long) {
mProgress += (long) msg.obj;
}
break;
case STATE_UPDATE_PROGRESS:
if (msg.obj == null) {
mProgress = updateBlockProgress();
} else if (msg.obj instanceof Long) {
mProgress = (long) msg.obj;
}
break;
}
return false;
}
/**
* 退出looper循环
*/
@@ -138,6 +152,10 @@ public class ThreadStateManager implements IThreadState {
return mProgress;
}
@Override public Handler.Callback getHandlerCallback() {
return callback;
}
/**
* 所有子线程是否都已经停止
*/
@@ -226,4 +244,8 @@ public class ThreadStateManager implements IThreadState {
return false;
}
}
@Override public void accept(ILoaderVisitor visitor) {
visitor.addComponent(this);
}
}

View File

@@ -16,7 +16,7 @@
package com.arialyy.aria.core.task;
import com.arialyy.aria.core.download.AbsGroupTaskWrapper;
import com.arialyy.aria.core.group.AbsGroupUtil;
import com.arialyy.aria.core.group.AbsGroupLoaderUtil;
/**
* Created by AriaL on 2017/6/29.
@@ -36,7 +36,7 @@ public abstract class AbsGroupTask<TASK_ENTITY extends AbsGroupTaskWrapper>
*/
public void startSubTask(String url) {
if (getUtil() != null) {
((AbsGroupUtil) getUtil()).startSubTask(url);
((AbsGroupLoaderUtil) getUtil()).startSubTask(url);
}
}
@@ -47,7 +47,7 @@ public abstract class AbsGroupTask<TASK_ENTITY extends AbsGroupTaskWrapper>
*/
public void stopSubTask(String url) {
if (getUtil() != null) {
((AbsGroupUtil) getUtil()).stopSubTask(url);
((AbsGroupLoaderUtil) getUtil()).stopSubTask(url);
}
}
}

View File

@@ -87,4 +87,10 @@ public interface IThreadTask extends Callable<IThreadTask> {
* @return {@code true} 分块分大小正常,{@code false} 分块大小错误
*/
boolean checkBlock();
/**
* 获取线程id
* @return
*/
int getThreadId();
}

View File

@@ -228,6 +228,10 @@ public class ThreadTask implements IThreadTask, IThreadTaskObserver {
return true;
}
@Override public int getThreadId() {
return mRecord.threadId;
}
/**
* 停止任务
*/

View File

@@ -19,7 +19,7 @@ package com.arialyy.aria.util;
import android.text.TextUtils;
import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.download.DownloadGroupEntity;
import com.arialyy.aria.core.inf.IRecordHandler;
import com.arialyy.aria.core.loader.IRecordHandler;
import com.arialyy.aria.core.upload.UploadEntity;
import com.arialyy.aria.orm.DbEntity;
import java.lang.reflect.Modifier;

View File

@@ -23,7 +23,7 @@ import com.arialyy.aria.core.common.AbsNormalEntity;
import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.download.DownloadGroupEntity;
import com.arialyy.aria.core.download.M3U8Entity;
import com.arialyy.aria.core.inf.IRecordHandler;
import com.arialyy.aria.core.loader.IRecordHandler;
import com.arialyy.aria.core.upload.UploadEntity;
import com.arialyy.aria.core.wrapper.ITaskWrapper;
import com.arialyy.aria.core.wrapper.RecordWrapper;