用于 Android 需要同步或異步執(zhí)行多個(gè)異步任務(wù),并且需要統(tǒng)一回調(diào)的情形。
思路很簡(jiǎn)單,通過(guò)一個(gè)隊(duì)列保存異步任務(wù),通過(guò)計(jì)數(shù)器或者從隊(duì)列一個(gè)個(gè)取出來(lái)執(zhí)行,實(shí)現(xiàn)所有任務(wù)完成后統(tǒng)一回調(diào)。
源碼如下
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import java.util.ArrayDeque;
/**
* 用于執(zhí)行多個(gè)異步任務(wù),并且在所有任務(wù)完成后統(tǒng)一回調(diào)的任務(wù)類(Java 8 使用編程效率更佳)
* 使用時(shí)先實(shí)例化該類,傳入監(jiān)聽(tīng)類,然后調(diào)用 addTask() 類添加任務(wù),最后執(zhí)行 execute() 方法。
* 支持超時(shí)回調(diào),默認(rèn)超時(shí)時(shí)間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ù)時(shí)不允許中途添加任務(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;
}
}
}
/**
* 單個(gè)異步任務(wù)類,需繼承后實(shí)現(xiàn) taskRun() 方法,并且需要在異步任務(wù)完成后調(diào)用 finishTask(), 否則不會(huì)被認(rèn)為
* 任務(wù)已完成,當(dāng)做超時(shí)處理
*/
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ù)時(shí)調(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();