Można też po prostu zmniejszamy licznik w obiekcie udostępnionym w ramach onPostExecute
. Ponieważ onPostExecute
działa na tym samym wątku (głównym wątku), nie musisz się martwić o synchronizację.
UPDATE 1
Wspólna obiekt może wyglądać następująco:
public class WorkCounter {
private int runningTasks;
private final Context ctx;
public WorkCounter(int numberOfTasks, Context ctx) {
this.runningTasks = numberOfTasks;
this.ctx = ctx;
}
// Only call this in onPostExecute! (or add synchronized to method declaration)
public void taskFinished() {
if (--runningTasks == 0) {
LocalBroadcastManager mgr = LocalBroadcastManager.getInstance(this.ctx);
mgr.sendBroadcast(new Intent("all_tasks_have_finished"));
}
}
}
UPDATE 2
Zgodnie z uwagami do tej odpowiedzi, PO szuka rozwiązania w którym może uniknąć budowania nowej klasy. Można to zrobić poprzez dzielenie AtomicInteger
wśród potomnych AsyncTask
s:
// TODO Update type params according to your needs.
public class MyAsyncTask extends AsyncTask<Void,Void,Void> {
// This instance should be created before creating your async tasks.
// Its start count should be equal to the number of async tasks that you will spawn.
// It is important that the same AtomicInteger is supplied to all the spawned async tasks such that they share the same work counter.
private final AtomicInteger workCounter;
public MyAsyncTask(AtomicInteger workCounter) {
this.workCounter = workCounter;
}
// TODO implement doInBackground
@Override
public void onPostExecute(Void result) {
// Job is done, decrement the work counter.
int tasksLeft = this.workCounter.decrementAndGet();
// If the count has reached zero, all async tasks have finished.
if (tasksLeft == 0) {
// Make activity aware by sending a broadcast.
LocalBroadcastManager mgr = LocalBroadcastManager.getInstance(this.ctx);
mgr.sendBroadcast(new Intent("all_tasks_have_finished"));
}
}
}
Jeśli chcesz czekać, to wolałbym za pomocą gwintu, jak można po prostu dołączyć do wątku. Cały sens używania Async polega na tym, że jest wykonywany równolegle. Na pewno możesz poczekać na wynik, używając Future dla Async. –
Czy masz kontrolę nad 'AsyncTask's i czy znasz liczbę zadań z góry? jeśli tak, możesz po prostu odliczać (liczbę całkowitą, bez wymyślnej synchronizacji) liczbę zakończonych zadań w 'onPostExecute()' i działać, gdy liczba osiągnie zero. – dhke
@dhke w tym przypadku musisz uruchomić bezczynną pętlę i nie podoba mi się to zbytnio –