From ad6ea4fac910f3112196732c1fce908d89c5e1a8 Mon Sep 17 00:00:00 2001 From: AriaLyy <511455842@qq.com> Date: Sun, 4 Jun 2017 18:37:01 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96Scheduler=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/arialyy/aria/core/AriaManager.java | 8 + .../com/arialyy/aria/core/ConfigHelper.java | 2 +- .../aria/core/download/DownloadTarget.java | 13 ++ .../aria/core/download/DownloadUtil.java | 3 +- .../aria/core/download/SingleThreadTask.java | 23 +-- .../aria/core/scheduler/AbsSchedulers.java | 190 ++++++++++++++++++ .../core/scheduler/DownloadSchedulers.java | 171 +--------------- .../aria/core/scheduler/UploadSchedulers.java | 153 +------------- .../java/com/arialyy/aria/orm/SqlHelper.java | 2 +- 9 files changed, 230 insertions(+), 335 deletions(-) create mode 100644 Aria/src/main/java/com/arialyy/aria/core/scheduler/AbsSchedulers.java diff --git a/Aria/src/main/java/com/arialyy/aria/core/AriaManager.java b/Aria/src/main/java/com/arialyy/aria/core/AriaManager.java index f03240b6..3b2f54bf 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/AriaManager.java +++ b/Aria/src/main/java/com/arialyy/aria/core/AriaManager.java @@ -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 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); + } } /** diff --git a/Aria/src/main/java/com/arialyy/aria/core/ConfigHelper.java b/Aria/src/main/java/com/arialyy/aria/core/ConfigHelper.java index ccbe918d..191101a2 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/ConfigHelper.java +++ b/Aria/src/main/java/com/arialyy/aria/core/ConfigHelper.java @@ -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; diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/DownloadTarget.java b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadTarget.java index 4d6c8ab7..44bc443c 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/DownloadTarget.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadTarget.java @@ -129,6 +129,8 @@ public class DownloadTarget extends AbsTarget " + 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)); diff --git a/Aria/src/main/java/com/arialyy/aria/core/scheduler/AbsSchedulers.java b/Aria/src/main/java/com/arialyy/aria/core/scheduler/AbsSchedulers.java new file mode 100644 index 00000000..3942ca61 --- /dev/null +++ b/Aria/src/main/java/com/arialyy/aria/core/scheduler/AbsSchedulers.java @@ -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, QUEUE extends ITaskQueue> + implements ISchedulers { + private static final String TAG = "AbsSchedulers"; + + protected QUEUE mQueue; + + private Map> mSchedulerListeners = + new ConcurrentHashMap<>(); + + @Override + public void addSchedulerListener(String targetName, ISchedulerListener schedulerListener) { + mSchedulerListeners.put(targetName, (IDownloadSchedulerListener) schedulerListener); + } + + @Override public void removeSchedulerListener(String targetName, + ISchedulerListener schedulerListener) { + //该内存泄露解决方案:http://stackoverflow.com/questions/14585829/how-safe-is-to-delete-already-removed-concurrenthashmap-element + for (Iterator>> iter = + mSchedulerListeners.entrySet().iterator(); iter.hasNext(); ) { + Map.Entry> 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 keys = mSchedulerListeners.keySet(); + for (String key : keys) { + callback(state, task, mSchedulerListeners.get(key)); + } + } + } + + private void callback(int state, TASK task, IDownloadSchedulerListener 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); + } + } +} diff --git a/Aria/src/main/java/com/arialyy/aria/core/scheduler/DownloadSchedulers.java b/Aria/src/main/java/com/arialyy/aria/core/scheduler/DownloadSchedulers.java index 43b6016f..a84875ac 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/scheduler/DownloadSchedulers.java +++ b/Aria/src/main/java/com/arialyy/aria/core/scheduler/DownloadSchedulers.java @@ -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 { +public class DownloadSchedulers + extends AbsSchedulers { private static final String TAG = "DownloadSchedulers"; private static final Object LOCK = new Object(); private static volatile DownloadSchedulers INSTANCE = null; - /** - * 下载器任务监听 - */ - private Map> mSchedulerListeners = - new ConcurrentHashMap<>(); - private DownloadTaskQueue mQueue; - private DownloadSchedulers() { mQueue = DownloadTaskQueue.getInstance(); } @@ -57,156 +44,4 @@ public class DownloadSchedulers implements ISchedulers { } return INSTANCE; } - - @Override public void addSchedulerListener(String targetName, - ISchedulerListener schedulerListener) { - mSchedulerListeners.put(targetName, - (IDownloadSchedulerListener) schedulerListener); - } - - @Override public void removeSchedulerListener(String targetName, - ISchedulerListener schedulerListener) { - //该内存溢出解决方案:http://stackoverflow.com/questions/14585829/how-safe-is-to-delete-already-removed-concurrenthashmap-element - for (Iterator>> iter = - mSchedulerListeners.entrySet().iterator(); iter.hasNext(); ) { - Map.Entry> 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 keys = mSchedulerListeners.keySet(); - for (String key : keys) { - callback(state, task, mSchedulerListeners.get(key)); - } - } - } - - private void callback(int state, DownloadTask task, - IDownloadSchedulerListener 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); - } - } } diff --git a/Aria/src/main/java/com/arialyy/aria/core/scheduler/UploadSchedulers.java b/Aria/src/main/java/com/arialyy/aria/core/scheduler/UploadSchedulers.java index d2077881..5401bc1a 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/scheduler/UploadSchedulers.java +++ b/Aria/src/main/java/com/arialyy/aria/core/scheduler/UploadSchedulers.java @@ -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 { +public class UploadSchedulers + extends AbsSchedulers { private static final String TAG = "UploadSchedulers"; private static final Object LOCK = new Object(); private static volatile UploadSchedulers INSTANCE = null; - private Map> mSchedulerListeners = - new ConcurrentHashMap<>(); - private UploadTaskQueue mQueue; private UploadSchedulers() { mQueue = UploadTaskQueue.getInstance(); @@ -53,141 +43,4 @@ public class UploadSchedulers implements ISchedulers { return INSTANCE; } - - @Override public void addSchedulerListener(String targetName, - ISchedulerListener schedulerListener) { - mSchedulerListeners.put(targetName, schedulerListener); - } - - @Override public void removeSchedulerListener(String targetName, - ISchedulerListener schedulerListener) { - for (Iterator>> iter = - mSchedulerListeners.entrySet().iterator(); iter.hasNext(); ) { - Map.Entry> 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 keys = mSchedulerListeners.keySet(); - for (String key : keys) { - callback(state, task, mSchedulerListeners.get(key)); - } - } - } - - private void callback(int state, UploadTask task, ISchedulerListener 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; - } } diff --git a/Aria/src/main/java/com/arialyy/aria/orm/SqlHelper.java b/Aria/src/main/java/com/arialyy/aria/orm/SqlHelper.java index f3f82bde..e13f5492 100644 --- a/Aria/src/main/java/com/arialyy/aria/orm/SqlHelper.java +++ b/Aria/src/main/java/com/arialyy/aria/orm/SqlHelper.java @@ -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) {