修复网络异常时,过度回调的问题

pull/330/head
laoyuyu 7 years ago
parent ebe0173074
commit b2f1141247
  1. 4
      Aria/src/main/java/com/arialyy/aria/core/command/normal/ResumeAllCmd.java
  2. 4
      Aria/src/main/java/com/arialyy/aria/core/common/AbsFileer.java
  3. 24
      Aria/src/main/java/com/arialyy/aria/core/common/AbsThreadTask.java
  4. 12
      Aria/src/main/java/com/arialyy/aria/core/common/StateConstance.java
  5. 3
      Aria/src/main/java/com/arialyy/aria/core/download/BaseDListener.java
  6. 19
      Aria/src/main/java/com/arialyy/aria/core/download/downloader/AbsGroupUtil.java
  7. 10
      Aria/src/main/java/com/arialyy/aria/core/download/downloader/FtpThreadTask.java
  8. 44
      Aria/src/main/java/com/arialyy/aria/core/download/downloader/HttpThreadTask.java
  9. 8
      Aria/src/main/java/com/arialyy/aria/core/queue/AbsTaskQueue.java
  10. 5
      Aria/src/main/java/com/arialyy/aria/core/scheduler/AbsSchedulers.java
  11. 5
      app/src/main/java/com/arialyy/simple/common/ConnectionChangeReceiver.java
  12. 6
      app/src/main/java/com/arialyy/simple/download/multi_download/FileListAdapter.java
  13. 1
      app/src/main/java/com/arialyy/simple/download/multi_download/MultiDownloadActivity.java

@ -27,7 +27,7 @@ import java.util.List;
* 1.如果执行队列没有满则开始下载任务直到执行队列满 * 1.如果执行队列没有满则开始下载任务直到执行队列满
* 2.如果队列执行队列已经满了则将所有任务添加到等待队列中 * 2.如果队列执行队列已经满了则将所有任务添加到等待队列中
* 3.如果队列中只有等待状态的任务如果执行队列没有满则会启动等待状态的任务如果执行队列已经满了则会将所有等待状态的任务加载到缓存队列中 * 3.如果队列中只有等待状态的任务如果执行队列没有满则会启动等待状态的任务如果执行队列已经满了则会将所有等待状态的任务加载到缓存队列中
* 4.恢复下载的任务规则是停止时间越晚的任务启动越早安装DESC来进行排序 * 4.恢复下载的任务规则是停止时间越晚的任务启动越早按照DESC来进行排序
*/ */
final class ResumeAllCmd<T extends AbsTaskEntity> extends AbsNormalCmd<T> { final class ResumeAllCmd<T extends AbsTaskEntity> extends AbsNormalCmd<T> {
private List<AbsTaskEntity> mWaitList = new ArrayList<>(); private List<AbsTaskEntity> mWaitList = new ArrayList<>();
@ -96,7 +96,7 @@ final class ResumeAllCmd<T extends AbsTaskEntity> extends AbsNormalCmd<T> {
int state = te.getState(); int state = te.getState();
if (state == IEntity.STATE_STOP || state == IEntity.STATE_OTHER) { if (state == IEntity.STATE_STOP || state == IEntity.STATE_OTHER) {
resumeEntity(te); resumeEntity(te);
} else if (state == IEntity.STATE_WAIT) { } else if (state == IEntity.STATE_WAIT || state == IEntity.STATE_FAIL) {
mWaitList.add(te); mWaitList.add(te);
} else if (state == IEntity.STATE_RUNNING) { } else if (state == IEntity.STATE_RUNNING) {
if (!mQueue.taskIsRunning(te.getEntity().getKey())) { if (!mQueue.taskIsRunning(te.getEntity().getKey())) {

@ -535,9 +535,7 @@ public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_ENTITY exte
AbsThreadTask task = mTask.get(key); AbsThreadTask task = mTask.get(key);
if (task != null && !task.isThreadComplete()) { if (task != null && !task.isThreadComplete()) {
task.getConfig().START_LOCATION = task.getConfig().THREAD_RECORD.startLocation; task.getConfig().START_LOCATION = task.getConfig().THREAD_RECORD.startLocation;
mConstance.isStop = false; mConstance.resetState();
mConstance.isCancel = false;
mConstance.isRunning = true;
startTimer(); startTimer();
ALog.d(TAG, String.format("任务【%s】开始重试,线程__%s__【开始位置:%s,结束位置:%s】", mEntity.getFileName(), ALog.d(TAG, String.format("任务【%s】开始重试,线程__%s__【开始位置:%s,结束位置:%s】", mEntity.getFileName(),
key, task.getConfig().START_LOCATION, task.getConfig().END_LOCATION)); key, task.getConfig().START_LOCATION, task.getConfig().END_LOCATION));

@ -245,7 +245,7 @@ public abstract class AbsThreadTask<ENTITY extends AbsNormalEntity, TASK_ENTITY
protected void fail(final long subCurrentLocation, String msg, Exception ex, boolean needRetry) { protected void fail(final long subCurrentLocation, String msg, Exception ex, boolean needRetry) {
synchronized (AriaManager.LOCK) { synchronized (AriaManager.LOCK) {
if (ex != null) { if (ex != null) {
ALog.e(TAG, msg + "\n" + ALog.getExceptionString(ex)); //ALog.e(TAG, msg + "\n" + ALog.getExceptionString(ex));
} else { } else {
ALog.e(TAG, msg); ALog.e(TAG, msg);
} }
@ -280,7 +280,7 @@ public abstract class AbsThreadTask<ENTITY extends AbsNormalEntity, TASK_ENTITY
mFailTimer.schedule(new TimerTask() { mFailTimer.schedule(new TimerTask() {
@Override public void run() { @Override public void run() {
if (isBreak()) { if (isBreak()) {
handleSailState(false); handleFailState(false);
return; return;
} }
mFailTimes++; mFailTimes++;
@ -292,7 +292,7 @@ public abstract class AbsThreadTask<ENTITY extends AbsNormalEntity, TASK_ENTITY
} }
}, RETRY_INTERVAL); }, RETRY_INTERVAL);
} else { } else {
handleSailState(!isBreak()); handleFailState(!isBreak());
} }
} }
@ -301,13 +301,17 @@ public abstract class AbsThreadTask<ENTITY extends AbsNormalEntity, TASK_ENTITY
* *
* @param taskNeedReTry 任务是否需要重试{@code true} 需要 * @param taskNeedReTry 任务是否需要重试{@code true} 需要
*/ */
private void handleSailState(boolean taskNeedReTry) { private void handleFailState(boolean taskNeedReTry) {
STATE.FAIL_NUM++; synchronized (AriaManager.LOCK) {
if (STATE.isFail()) { STATE.FAIL_NUM++;
STATE.isRunning = false; if (STATE.isFail()) {
STATE.isStop = true; STATE.isRunning = false;
ALog.e(TAG, String.format("任务【%s】执行失败", mConfig.TEMP_FILE.getName())); // 手动停止不进行fail回调
mListener.onFail(taskNeedReTry); if (!STATE.isStop) {
ALog.e(TAG, String.format("任务【%s】执行失败", mConfig.TEMP_FILE.getName()));
mListener.onFail(taskNeedReTry);
}
}
} }
} }

@ -15,17 +15,20 @@
*/ */
package com.arialyy.aria.core.common; package com.arialyy.aria.core.common;
import com.arialyy.aria.util.ALog;
/** /**
* Created by lyy on 2017/1/18. * Created by lyy on 2017/1/18.
* 状态常量 * 状态常量
*/ */
public class StateConstance { public class StateConstance {
private static final String TAG = "StateConstance";
public int CANCEL_NUM = 0; public int CANCEL_NUM = 0;
public int STOP_NUM = 0; public int STOP_NUM = 0;
public int FAIL_NUM = 0; public int FAIL_NUM = 0;
public int COMPLETE_THREAD_NUM = 0; public int COMPLETE_THREAD_NUM = 0;
public int START_THREAD_NUM; //启动的线程数 public int START_THREAD_NUM; //启动的线程数
public long CURRENT_LOCATION = 0; public long CURRENT_LOCATION = 0; //当前下载进度
public boolean isRunning = false; public boolean isRunning = false;
public boolean isCancel = false; public boolean isCancel = false;
public boolean isStop = false; public boolean isStop = false;
@ -38,7 +41,6 @@ public class StateConstance {
isCancel = false; isCancel = false;
isStop = false; isStop = false;
isRunning = true; isRunning = true;
CURRENT_LOCATION = 0;
CANCEL_NUM = 0; CANCEL_NUM = 0;
STOP_NUM = 0; STOP_NUM = 0;
FAIL_NUM = 0; FAIL_NUM = 0;
@ -55,15 +57,17 @@ public class StateConstance {
* 所有子线程是否都已经失败 * 所有子线程是否都已经失败
*/ */
public boolean isFail() { public boolean isFail() {
ALog.d(TAG, String.format("fail_num=%s; start_thread_num=%s, complete_num=%s", FAIL_NUM,
START_THREAD_NUM, COMPLETE_THREAD_NUM));
return COMPLETE_THREAD_NUM != START_THREAD_NUM return COMPLETE_THREAD_NUM != START_THREAD_NUM
&& FAIL_NUM + COMPLETE_THREAD_NUM >= START_THREAD_NUM; && FAIL_NUM == START_THREAD_NUM;
} }
/** /**
* 所有子线程是否都已经完成 * 所有子线程是否都已经完成
*/ */
public boolean isComplete() { public boolean isComplete() {
return COMPLETE_THREAD_NUM >= START_THREAD_NUM; return COMPLETE_THREAD_NUM == START_THREAD_NUM;
} }
/** /**

@ -174,7 +174,8 @@ class BaseDListener<ENTITY extends AbsEntity, TASK_ENTITY extends AbsTaskEntity<
} else if (mEntity.isComplete()) { } else if (mEntity.isComplete()) {
mEntity.setCompleteTime(System.currentTimeMillis()); mEntity.setCompleteTime(System.currentTimeMillis());
mEntity.setCurrentProgress(mEntity.getFileSize()); mEntity.setCurrentProgress(mEntity.getFileSize());
} else if (location > 0) { }
if (location > 0) {
mEntity.setCurrentProgress(location); mEntity.setCurrentProgress(location);
} }
mTaskEntity.update(); mTaskEntity.update();

@ -262,9 +262,8 @@ public abstract class AbsGroupUtil implements IUtil {
dt.stop(); dt.stop();
} }
} }
if (mDownloaderMap.size() == 0) { clearState();
mListener.onStop(mCurrentLocation); mListener.onStop(mCurrentLocation);
}
} }
protected void onStop() { protected void onStop() {
@ -279,7 +278,7 @@ public abstract class AbsGroupUtil implements IUtil {
mListener.onPre(); mListener.onPre();
mGroupSize = mGTEntity.getSubTaskEntities().size(); mGroupSize = mGTEntity.getSubTaskEntities().size();
mTotalLen = mGTEntity.getEntity().getFileSize(); mTotalLen = mGTEntity.getEntity().getFileSize();
isNeedLoadFileSize = mTotalLen <= 1; isNeedLoadFileSize = mTotalLen <= 10;
for (DownloadTaskEntity te : mGTEntity.getSubTaskEntities()) { for (DownloadTaskEntity te : mGTEntity.getSubTaskEntities()) {
File file = new File(te.getKey()); File file = new File(te.getKey());
if (te.getState() == IEntity.STATE_COMPLETE && file.exists()) { if (te.getState() == IEntity.STATE_COMPLETE && file.exists()) {
@ -455,7 +454,7 @@ public abstract class AbsGroupUtil implements IUtil {
mListener.onSubStop(subEntity); mListener.onSubStop(subEntity);
synchronized (AbsGroupUtil.LOCK) { synchronized (AbsGroupUtil.LOCK) {
mStopNum++; mStopNum++;
if (mStopNum + mCompleteNum + mFailMap.size() == mGroupSize) { if (mStopNum + mCompleteNum + mFailMap.size() == mGroupSize && !isStop) {
closeTimer(false); closeTimer(false);
mListener.onStop(mCurrentLocation); mListener.onStop(mCurrentLocation);
} }
@ -479,7 +478,9 @@ public abstract class AbsGroupUtil implements IUtil {
if (mCompleteNum == mGroupSize) { if (mCompleteNum == mGroupSize) {
closeTimer(false); closeTimer(false);
mListener.onComplete(); mListener.onComplete();
} else if (mFailMap.size() > 0 && mStopNum + mCompleteNum + mFailMap.size() >= mGroupSize) { } else if (mFailMap.size() > 0
&& mStopNum + mCompleteNum + mFailMap.size() >= mGroupSize
&& !isStop) {
//如果子任务完成数量加上失败的数量和总任务数一致,则任务组停止下载 //如果子任务完成数量加上失败的数量和总任务数一致,则任务组停止下载
closeTimer(false); closeTimer(false);
mListener.onStop(mCurrentLocation); mListener.onStop(mCurrentLocation);
@ -500,10 +501,10 @@ public abstract class AbsGroupUtil implements IUtil {
private void reTry(boolean needRetry) { private void reTry(boolean needRetry) {
Downloader dt = mDownloaderMap.get(subEntity.getUrl()); Downloader dt = mDownloaderMap.get(subEntity.getUrl());
synchronized (AbsGroupUtil.LOCK) { synchronized (AbsGroupUtil.LOCK) {
if (dt != null if (!isCancel && !isStop && dt != null
&& !dt.isBreak() && !dt.isBreak()
&& needRetry && needRetry
&& subEntity.getFailNum() < 5 && subEntity.getFailNum() < 3
&& (NetUtils.isConnected(AriaManager.APP) || isNotNetRetry)) { && (NetUtils.isConnected(AriaManager.APP) || isNotNetRetry)) {
reStartTask(dt); reStartTask(dt);
} else { } else {
@ -533,7 +534,7 @@ public abstract class AbsGroupUtil implements IUtil {
dt.retryThreadTask(); dt.retryThreadTask();
} }
} }
}, 3000); }, 5000);
} }
private void handleSpeed(long speed) { private void handleSpeed(long speed) {

@ -101,12 +101,8 @@ class FtpThreadTask extends AbsFtpThreadTask<DownloadEntity, DownloadTaskEntity>
readDynamicFile(is); readDynamicFile(is);
} else { } else {
readNormal(is); readNormal(is);
handleComplete();
} }
if (isBreak()) {
return;
}
handleComplete();
} catch (IOException e) { } catch (IOException e) {
fail(mChildCurrentLocation, String.format("下载失败【%s】", mConfig.URL), e); fail(mChildCurrentLocation, String.format("下载失败【%s】", mConfig.URL), e);
} catch (Exception e) { } catch (Exception e) {
@ -129,6 +125,9 @@ class FtpThreadTask extends AbsFtpThreadTask<DownloadEntity, DownloadTaskEntity>
* 处理线程完成的情况 * 处理线程完成的情况
*/ */
private void handleComplete() { private void handleComplete() {
if (isBreak()) {
return;
}
ALog.i(TAG, ALog.i(TAG,
String.format("任务【%s】线程__%s__下载完毕", mConfig.TEMP_FILE.getName(), mConfig.THREAD_ID)); String.format("任务【%s】线程__%s__下载完毕", mConfig.TEMP_FILE.getName(), mConfig.THREAD_ID));
writeConfig(true, mConfig.END_LOCATION); writeConfig(true, mConfig.END_LOCATION);
@ -178,6 +177,7 @@ class FtpThreadTask extends AbsFtpThreadTask<DownloadEntity, DownloadTaskEntity>
bf.compact(); bf.compact();
progress(len); progress(len);
} }
handleComplete();
} catch (InterruptedException e) { } catch (InterruptedException e) {
e.printStackTrace(); e.printStackTrace();
} catch (IOException e) { } catch (IOException e) {

@ -99,12 +99,8 @@ final class HttpThreadTask extends AbsThreadTask<DownloadEntity, DownloadTaskEnt
} else { } else {
readNormal(is, file); readNormal(is, file);
} }
handleComplete();
} }
if (isBreak()) {
return;
}
handleComplete();
} catch (MalformedURLException e) { } catch (MalformedURLException e) {
fail(mChildCurrentLocation, "下载链接异常", e); fail(mChildCurrentLocation, "下载链接异常", e);
} catch (IOException e) { } catch (IOException e) {
@ -153,6 +149,7 @@ final class HttpThreadTask extends AbsThreadTask<DownloadEntity, DownloadTaskEnt
bf.compact(); bf.compact();
progress(len); progress(len);
} }
handleComplete();
} catch (InterruptedException e) { } catch (InterruptedException e) {
e.printStackTrace(); e.printStackTrace();
} catch (IOException e) { } catch (IOException e) {
@ -207,29 +204,28 @@ final class HttpThreadTask extends AbsThreadTask<DownloadEntity, DownloadTaskEnt
* 处理完成配置文件的更新或事件回调 * 处理完成配置文件的更新或事件回调
*/ */
private void handleComplete() { private void handleComplete() {
if (isBreak()) {
return;
}
//支持断点的处理 //支持断点的处理
if (mConfig.SUPPORT_BP) { if (mConfig.SUPPORT_BP) {
if (mChildCurrentLocation == mConfig.END_LOCATION) { ALog.i(TAG,
ALog.i(TAG, String.format("任务【%s】线程__%s__下载完毕", mConfig.TEMP_FILE.getName(), mConfig.THREAD_ID));
String.format("任务【%s】线程__%s__下载完毕", mConfig.TEMP_FILE.getName(), mConfig.THREAD_ID)); writeConfig(true, mConfig.END_LOCATION);
writeConfig(true, mConfig.END_LOCATION); STATE.COMPLETE_THREAD_NUM++;
STATE.COMPLETE_THREAD_NUM++; if (STATE.isComplete()) {
if (STATE.isComplete()) { if (isBlock) {
if (isBlock) { boolean success = mergeFile();
boolean success = mergeFile(); if (!success) {
if (!success) { ALog.e(TAG, String.format("任务【%s】分块文件合并失败", mConfig.TEMP_FILE.getName()));
ALog.e(TAG, String.format("任务【%s】分块文件合并失败", mConfig.TEMP_FILE.getName())); STATE.isRunning = false;
STATE.isRunning = false; mListener.onFail(false);
mListener.onFail(false); return;
return;
}
} }
STATE.TASK_RECORD.deleteData();
STATE.isRunning = false;
mListener.onComplete();
} }
} else { STATE.TASK_RECORD.deleteData();
STATE.FAIL_NUM++; STATE.isRunning = false;
mListener.onComplete();
} }
if (STATE.isFail()) { if (STATE.isFail()) {
STATE.isRunning = false; STATE.isRunning = false;

@ -67,16 +67,10 @@ abstract class AbsTaskQueue<TASK extends AbsTask, TASK_ENTITY extends AbsTaskEnt
* 停止所有任务 * 停止所有任务
*/ */
@Override public void stopAllTask() { @Override public void stopAllTask() {
//for(String key : mCachePool.getAllTask().keySet()){
// TASK task = mCachePool.getAllTask().get(key);
// if (task != null){
// task.stop();
// }
//}
mCachePool.clear(); mCachePool.clear();
for (String key : mExecutePool.getAllTask().keySet()) { for (String key : mExecutePool.getAllTask().keySet()) {
TASK task = mExecutePool.getAllTask().get(key); TASK task = mExecutePool.getAllTask().get(key);
if (task != null && task.isRunning()) { if (task != null && (task.isRunning() || task.getState() == IEntity.STATE_FAIL)) {
task.stop(); task.stop();
} }
} }

@ -168,11 +168,13 @@ abstract class AbsSchedulers<TASK_ENTITY extends AbsTaskEntity, TASK extends Abs
case CANCEL: case CANCEL:
mQueue.removeTaskFormQueue(task.getKey()); mQueue.removeTaskFormQueue(task.getKey());
if (mQueue.getCurrentExePoolNum() < mQueue.getMaxTaskNum()) { if (mQueue.getCurrentExePoolNum() < mQueue.getMaxTaskNum()) {
ALog.d(TAG, "stop_next");
startNextTask(); startNextTask();
} }
break; break;
case COMPLETE: case COMPLETE:
mQueue.removeTaskFormQueue(task.getKey()); mQueue.removeTaskFormQueue(task.getKey());
ALog.d(TAG, "complete_next");
startNextTask(); startNextTask();
break; break;
case FAIL: case FAIL:
@ -258,6 +260,7 @@ abstract class AbsSchedulers<TASK_ENTITY extends AbsTaskEntity, TASK extends Abs
private void handleFailTask(final TASK task) { private void handleFailTask(final TASK task) {
if (!task.needRetry || task.isStop() || task.isCancel()) { if (!task.needRetry || task.isStop() || task.isCancel()) {
mQueue.removeTaskFormQueue(task.getKey()); mQueue.removeTaskFormQueue(task.getKey());
ALog.d(TAG, "fail_next");
startNextTask(); startNextTask();
return; return;
} }
@ -281,6 +284,7 @@ abstract class AbsSchedulers<TASK_ENTITY extends AbsTaskEntity, TASK extends Abs
callback(FAIL, task); callback(FAIL, task);
mQueue.removeTaskFormQueue(task.getKey()); mQueue.removeTaskFormQueue(task.getKey());
startNextTask(); startNextTask();
ALog.d(TAG, "retry_next");
TEManager.getInstance().removeTEntity(task.getKey()); TEManager.getInstance().removeTEntity(task.getKey());
return; return;
} }
@ -299,6 +303,7 @@ abstract class AbsSchedulers<TASK_ENTITY extends AbsTaskEntity, TASK extends Abs
} else { } else {
mQueue.removeTaskFormQueue(task.getKey()); mQueue.removeTaskFormQueue(task.getKey());
startNextTask(); startNextTask();
ALog.d(TAG, "retry_next_1");
TEManager.getInstance().removeTEntity(task.getKey()); TEManager.getInstance().removeTEntity(task.getKey());
} }
} }

@ -12,7 +12,7 @@ public class ConnectionChangeReceiver extends BroadcastReceiver {
private static final String TAG = ConnectionChangeReceiver.class.getSimpleName(); private static final String TAG = ConnectionChangeReceiver.class.getSimpleName();
@Override public void onReceive(Context context, Intent intent) { @Override public void onReceive(Context context, Intent intent) {
Log.d(TAG, "网络状态改变");
/** /**
* 获得网络连接服务 * 获得网络连接服务
*/ */
@ -23,11 +23,12 @@ public class ConnectionChangeReceiver extends BroadcastReceiver {
if (NetworkInfo.State.CONNECTED == state) { if (NetworkInfo.State.CONNECTED == state) {
Aria.download(this).resumeAllTask(); Aria.download(this).resumeAllTask();
Log.w(TAG, "恢复所有任务");
return; return;
} }
Aria.download(this).stopAllTask(); Aria.download(this).stopAllTask();
//Log.w(TAG, "停止所有任务");
//state = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE).getState(); //state = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE).getState();
//if (NetworkInfo.State.CONNECTED == state) { //if (NetworkInfo.State.CONNECTED == state) {
// //

@ -70,15 +70,15 @@ final class FileListAdapter extends AbsRVAdapter<FileListEntity, FileListAdapter
Toast.makeText(getContext(), "开始下载:" + item.name, Toast.LENGTH_SHORT).show(); Toast.makeText(getContext(), "开始下载:" + item.name, Toast.LENGTH_SHORT).show();
if (item.isGroup) { if (item.isGroup) {
Aria.download(getContext()) Aria.download(getContext())
.load(Arrays.asList(item.urls)) .loadGroup(Arrays.asList(item.urls))
.setSubFileName(Arrays.asList(item.names)) .setSubFileName(Arrays.asList(item.names))
.setDownloadDirPath(item.downloadPath) .setDirPath(item.downloadPath)
.setGroupAlias(item.name) .setGroupAlias(item.name)
.start(); .start();
} else { } else {
Aria.download(getContext()) Aria.download(getContext())
.load(item.key) .load(item.key)
.setDownloadPath(item.downloadPath) .setFilePath(item.downloadPath)
.start(); .start();
} }
} }

@ -144,6 +144,7 @@ public class MultiDownloadActivity extends BaseActivity<ActivityMultiDownloadBin
} }
@DownloadGroup.onTaskRunning() void groupTaskRunning(DownloadGroupTask task) { @DownloadGroup.onTaskRunning() void groupTaskRunning(DownloadGroupTask task) {
ALog.d(TAG, String.format("group【%s】running", task.getTaskName()));
mAdapter.setProgress(task.getEntity()); mAdapter.setProgress(task.getEntity());
} }

Loading…
Cancel
Save