parent
1a83617045
commit
dbddf3b4e2
@ -0,0 +1,64 @@ |
|||||||
|
/* |
||||||
|
* 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.download.group; |
||||||
|
|
||||||
|
import com.arialyy.aria.core.common.AbsFileer; |
||||||
|
|
||||||
|
/** |
||||||
|
* 组合任务子任务队列 |
||||||
|
* |
||||||
|
* @param <Fileer> {@link AbsFileer}下载器 |
||||||
|
*/ |
||||||
|
interface ISubQueue<Fileer extends AbsFileer> { |
||||||
|
|
||||||
|
/** |
||||||
|
* 添加任务 |
||||||
|
*/ |
||||||
|
|
||||||
|
void addTask(Fileer fileer); |
||||||
|
|
||||||
|
/** |
||||||
|
* 开始任务 |
||||||
|
*/ |
||||||
|
void startTask(Fileer fileer); |
||||||
|
|
||||||
|
/** |
||||||
|
* 停止任务 |
||||||
|
*/ |
||||||
|
void stopTask(Fileer fileer); |
||||||
|
|
||||||
|
/** |
||||||
|
* 修改最大任务数 |
||||||
|
* |
||||||
|
* @param num 任务数不能小于1 |
||||||
|
*/ |
||||||
|
void modifyMaxExecNum(int num); |
||||||
|
|
||||||
|
/** |
||||||
|
* 从执行队列中移除任务,一般用于任务完成的情况 |
||||||
|
*/ |
||||||
|
void removeTaskFromExecQ(Fileer fileer); |
||||||
|
|
||||||
|
/** |
||||||
|
* 删除任务 |
||||||
|
*/ |
||||||
|
void removeTask(Fileer fileer); |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取下一个任务 |
||||||
|
*/ |
||||||
|
Fileer getNextTask(); |
||||||
|
} |
@ -0,0 +1,115 @@ |
|||||||
|
/* |
||||||
|
* 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.download.group; |
||||||
|
|
||||||
|
import android.os.CountDownTimer; |
||||||
|
import android.os.Message; |
||||||
|
import com.arialyy.aria.core.AriaManager; |
||||||
|
import com.arialyy.aria.core.config.Configuration; |
||||||
|
import com.arialyy.aria.core.download.DownloadTask; |
||||||
|
import com.arialyy.aria.core.download.downloader.Downloader; |
||||||
|
import com.arialyy.aria.core.inf.AbsEntity; |
||||||
|
import com.arialyy.aria.core.scheduler.ISchedulers; |
||||||
|
import com.arialyy.aria.util.ALog; |
||||||
|
import com.arialyy.aria.util.NetUtils; |
||||||
|
|
||||||
|
/** |
||||||
|
* 组合任务子任务调度器,用于调度任务的开始、停止、失败、完成等情况 |
||||||
|
* 该调度器生命周期和{@link AbsGroupUtil}生命周期一致 |
||||||
|
*/ |
||||||
|
public class SimpleSchedulers implements ISchedulers<DownloadTask> { |
||||||
|
private static final String TAG = "SimpleSchedulers"; |
||||||
|
private SimpleSubQueue mQueue = SimpleSubQueue.newInstance(); |
||||||
|
|
||||||
|
private SimpleSchedulers() { |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
public static SimpleSchedulers newInstance() { |
||||||
|
|
||||||
|
return new SimpleSchedulers(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override public boolean handleMessage(Message msg) { |
||||||
|
Downloader loader = (Downloader) msg.obj; |
||||||
|
switch (msg.what) { |
||||||
|
case ADD: |
||||||
|
mQueue.addTask(loader); |
||||||
|
break; |
||||||
|
case START: |
||||||
|
mQueue.startTask(loader); |
||||||
|
break; |
||||||
|
case STOP: |
||||||
|
mQueue.stopTask(loader); |
||||||
|
startNext(); |
||||||
|
break; |
||||||
|
case COMPLETE: |
||||||
|
mQueue.removeTaskFromExecQ(loader); |
||||||
|
startNext(); |
||||||
|
case FAIL: |
||||||
|
break; |
||||||
|
} |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 如果有等待中的任务,则启动下一任务 |
||||||
|
*/ |
||||||
|
private void startNext() { |
||||||
|
Downloader next = mQueue.getNextTask(); |
||||||
|
if (next != null) { |
||||||
|
mQueue.startTask(next); |
||||||
|
} else { |
||||||
|
ALog.i(TAG, "没有下一任务"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 处理失败的任务 |
||||||
|
*/ |
||||||
|
private void handleFail(final Downloader loader) { |
||||||
|
Configuration config = Configuration.getInstance(); |
||||||
|
|
||||||
|
long interval = config.downloadCfg.getReTryInterval(); |
||||||
|
int num = config.downloadCfg.getReTryNum(); |
||||||
|
boolean isNotNetRetry = config.appCfg.isNotNetRetry(); |
||||||
|
|
||||||
|
final int reTryNum = num; |
||||||
|
if ((!NetUtils.isConnected(AriaManager.APP) && !isNotNetRetry) |
||||||
|
|| loader.getEntity().getFailNum() > reTryNum) { |
||||||
|
startNext(); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
CountDownTimer timer = new CountDownTimer(interval, 1000) { |
||||||
|
@Override public void onTick(long millisUntilFinished) { |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
@Override public void onFinish() { |
||||||
|
AbsEntity entity = loader.getEntity(); |
||||||
|
if (entity.getFailNum() <= reTryNum) { |
||||||
|
ALog.d(TAG, String.format("任务【%s】开始重试", loader.getEntity().getFileName())); |
||||||
|
loader.retryTask(); |
||||||
|
} else { |
||||||
|
startNext(); |
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
timer.start(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,145 @@ |
|||||||
|
/* |
||||||
|
* 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.download.group; |
||||||
|
|
||||||
|
import com.arialyy.aria.core.config.Configuration; |
||||||
|
import com.arialyy.aria.core.download.downloader.Downloader; |
||||||
|
import com.arialyy.aria.util.ALog; |
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.Collection; |
||||||
|
import java.util.Iterator; |
||||||
|
import java.util.LinkedHashMap; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Map; |
||||||
|
import java.util.Set; |
||||||
|
|
||||||
|
/** |
||||||
|
* 组合任务队列,该队列生命周期和{@link AbsGroupUtil}生命周期一致 |
||||||
|
*/ |
||||||
|
class SimpleSubQueue implements ISubQueue<Downloader> { |
||||||
|
private static final String TAG = "SimpleSubQueue"; |
||||||
|
/** |
||||||
|
* 缓存下载器 |
||||||
|
*/ |
||||||
|
private Map<String, Downloader> mCache = new LinkedHashMap<>(); |
||||||
|
/** |
||||||
|
* 执行中的下载器 |
||||||
|
*/ |
||||||
|
private Map<String, Downloader> mExec = new LinkedHashMap<>(); |
||||||
|
|
||||||
|
/** |
||||||
|
* 最大执行任务数 |
||||||
|
*/ |
||||||
|
private int mExecSize; |
||||||
|
|
||||||
|
private SimpleSubQueue() { |
||||||
|
mExecSize = Configuration.getInstance().dGroupCfg.getSubMaxTaskNum(); |
||||||
|
} |
||||||
|
|
||||||
|
static SimpleSubQueue newInstance() { |
||||||
|
return new SimpleSubQueue(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override public void addTask(Downloader fileer) { |
||||||
|
mCache.put(fileer.getKey(), fileer); |
||||||
|
} |
||||||
|
|
||||||
|
@Override public void startTask(Downloader fileer) { |
||||||
|
if (mExec.size() < mExecSize) { |
||||||
|
mCache.remove(fileer.getKey()); |
||||||
|
mExec.put(fileer.getKey(), fileer); |
||||||
|
fileer.start(); |
||||||
|
} else { |
||||||
|
ALog.d(TAG, String.format("执行队列已满,任务见缓冲到缓存器中,key: %s", fileer.getKey())); |
||||||
|
addTask(fileer); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override public void stopTask(Downloader fileer) { |
||||||
|
fileer.stop(); |
||||||
|
mExec.remove(fileer.getKey()); |
||||||
|
} |
||||||
|
|
||||||
|
@Override public void modifyMaxExecNum(int num) { |
||||||
|
if (num < 1) { |
||||||
|
ALog.e(TAG, String.format("修改组合任务子任务队列数失败,num: %s", num)); |
||||||
|
return; |
||||||
|
} |
||||||
|
if (num == mExecSize) { |
||||||
|
ALog.i(TAG, String.format("忽略此次修改,oldSize: %s, num: %s", mExecSize, num)); |
||||||
|
return; |
||||||
|
} |
||||||
|
int oldSize = mExecSize; |
||||||
|
mExecSize = num; |
||||||
|
int diff = Math.abs(oldSize - num); |
||||||
|
|
||||||
|
if (oldSize < num) { // 处理队列变小的情况,该情况下将停止队尾任务,并将这些任务添加到缓存队列中
|
||||||
|
if (mExec.size() > num) { |
||||||
|
Set<String> keys = mExec.keySet(); |
||||||
|
List<Downloader> caches = new ArrayList<>(); |
||||||
|
int i = 0; |
||||||
|
for (String key : keys) { |
||||||
|
if (i > num) { |
||||||
|
caches.add(mExec.get(key)); |
||||||
|
} |
||||||
|
i++; |
||||||
|
} |
||||||
|
Collection<Downloader> temp = mCache.values(); |
||||||
|
mCache.clear(); |
||||||
|
ALog.d(TAG, String.format("测试, map size: %s", mCache.size())); |
||||||
|
for (Downloader cache : caches) { |
||||||
|
addTask(cache); |
||||||
|
} |
||||||
|
for (Downloader t : temp) { |
||||||
|
addTask(t); |
||||||
|
} |
||||||
|
} |
||||||
|
} else { // 处理队列变大的情况,该情况下将增加任务
|
||||||
|
if (mExec.size() < num) { |
||||||
|
for (int i = 0; i < diff; i++) { |
||||||
|
Downloader next = getNextTask(); |
||||||
|
if (next != null) { |
||||||
|
startTask(next); |
||||||
|
} else { |
||||||
|
ALog.d(TAG, "子任务中没有缓存任务"); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override public void removeTaskFromExecQ(Downloader fileer) { |
||||||
|
if (mExec.containsKey(fileer.getKey())) { |
||||||
|
if (fileer.isRunning()) { |
||||||
|
fileer.stop(); |
||||||
|
} |
||||||
|
mExec.remove(fileer.getKey()); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override public void removeTask(Downloader fileer) { |
||||||
|
removeTaskFromExecQ(fileer); |
||||||
|
mCache.remove(fileer.getKey()); |
||||||
|
} |
||||||
|
|
||||||
|
@Override public Downloader getNextTask() { |
||||||
|
Iterator<String> keys = mCache.keySet().iterator(); |
||||||
|
if (keys.hasNext()) { |
||||||
|
return mCache.get(keys.next()); |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue