用于 Android 需要同步或異步執(zhí)行多個異步任務(wù),并且需要統(tǒng)一回調(diào)的情形。
思路很簡單,通過一個隊列保存異步任務(wù)挺尾,通過計數(shù)器或者從隊列一個個取出來執(zhí)行,實現(xiàn)所有任務(wù)完成后統(tǒng)一回調(diào)站绪。
源碼如下
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import java.util.ArrayDeque;
/**
* 用于執(zhí)行多個異步任務(wù)遭铺,并且在所有任務(wù)完成后統(tǒng)一回調(diào)的任務(wù)類(Java 8 使用編程效率更佳)
* 使用時先實例化該類,傳入監(jiān)聽類恢准,然后調(diào)用 addTask() 類添加任務(wù)魂挂,最后執(zhí)行 execute() 方法。
* 支持超時回調(diào)馁筐,默認超時時間5000毫秒
*/
public class MultiAsyncTask implements OnSingleTaskFinishListener {
private ArrayDeque<AsyncTask> taskQueue = new ArrayDeque<>();
private InvokeMode invokeMode;
private OnTasksFinishListener listener;
private final Object counterLock = new Object();
private final Object executeLock = new Object();
private int finishedTaskNumber = 0;
private int timeOut = 5000;
private boolean isExecuting = false;
public MultiAsyncTask(InvokeMode invokeMode, OnTasksFinishListener listener) {
this.invokeMode = invokeMode;
this.listener = listener;
}
public int getTimeOut() {
return timeOut;
}
public void setTimeOut(int timeOut) {
this.timeOut = timeOut;
}
@Override
public void onTaskFinish() {
synchronized (counterLock){
switch (invokeMode){
case SYNC:
if(taskQueue.isEmpty()){
finish();
}else{
AsyncTask task = taskQueue.pollFirst();
Thread t = new Thread(task);
t.start();
}
break;
case ASYNC:
finishedTaskNumber ++;
if(finishedTaskNumber == taskQueue.size()){
finish();
}
break;
}
}
}
@Override
public void onTimeOut() {
synchronized (executeLock) {
if (isExecuting) {
isExecuting = false;
try {
Class.forName("android.os.Build");
if (Build.VERSION.SDK_INT != 0) {
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
@Override
public void run() {
listener.onTimeOut();
}
});
return;
}
} catch (ClassNotFoundException ignored) {
}
listener.onTimeOut();
}
}
}
private void finish(){
try{
Class.forName("android.os.Build");
if (Build.VERSION.SDK_INT != 0)
{
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
@Override
public void run() {
listener.onFinish();
}
});
return;
}
} catch (ClassNotFoundException ignored){
}
listener.onFinish();
isExecuting = false;
}
public void addTask(AsyncTask task){
//執(zhí)行任務(wù)時不允許中途添加任務(wù)
if (!isExecuting){
task.setListener(this);
task.setTimeOut(timeOut);
taskQueue.add(task);
}
}
public void execute(){
synchronized (executeLock){
isExecuting = true;
finishedTaskNumber = 0;
if(taskQueue.isEmpty()){
return;
}
switch (invokeMode){
case SYNC:
AsyncTask task = taskQueue.pollFirst();
Thread t = new Thread(task);
t.start();
break;
case ASYNC:
for(AsyncTask task1 : taskQueue){
Thread t1 = new Thread(task1);
t1.start();
}
break;
}
}
}
/**
* 單個異步任務(wù)類涂召,需繼承后實現(xiàn) taskRun() 方法,并且需要在異步任務(wù)完成后調(diào)用 finishTask()敏沉, 否則不會被認為
* 任務(wù)已完成果正,當做超時處理
*/
public abstract static class AsyncTask implements Runnable{
private OnSingleTaskFinishListener listener;
private int timeOut = -1;
private boolean isTaskFinished = false;
public void setListener(OnSingleTaskFinishListener listener){
this.listener = listener;
}
public void setTimeOut(int timeOut) {
this.timeOut = timeOut;
}
@Override
public void run() {
taskRun();
if(timeOut != -1){
try {
Thread.sleep(timeOut);
if(!isTaskFinished){
listener.onTimeOut();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public abstract void taskRun();
/**
* 完成異步任務(wù)時調(diào)用該方法
*/
public void finishTask(){
isTaskFinished = true;
if(listener != null){
listener.onTaskFinish();
}
}
}
/**
* 執(zhí)行模式,同步與異步
*/
public enum InvokeMode{
SYNC, ASYNC
}
/**
* 所有任務(wù)執(zhí)行完成后回調(diào)
*/
public interface OnTasksFinishListener{
void onFinish();
void onTimeOut();
}
}
interface OnSingleTaskFinishListener{
void onTaskFinish();
void onTimeOut();
}
調(diào)用方式如下
MultiAsyncTask task = new MultiAsyncTask(MultiAsyncTask.InvokeMode.ASYNC, new MultiAsyncTask.OnTasksFinishListener() {
@Override
public void onFinish() {
ToastUtil.showShort("Bravo!!!!!");
}
@Override
public void onTimeOut() {
ToastUtil.showShort("Time Out!!!!!");
}
});
task.addTask(new MultiAsyncTask.AsyncTask(){
@Override
public void taskRun() {
//TODO do something
}
});
task.addTask(new MultiAsyncTask.AsyncTask(){
@Override
public void taskRun() {
//TODO do something
}
});
task.execute();