Well, I can see you are using java, so probably you aren't allowed for some reason to use coroutines. With coroutines, it would be easier to achieve such a result.
Consider using them, especially have a look at their way to solve your problem.
What I would use in your case is - CountDownLatch.
Your code will look similar to this one:
CountDownLatch latch = new CountDownLatch(applicationInfoList.size);
for (ApplicationInfo info : applicationInfoList) {
service.execute(new MyTask(info, latch));
}
latch.await();
MyTask under the hood should call latch.countDown() when your work is done.
latch.await() throws InterruptedException so it should be handled.
Note: Anyway, it blocks the thread you are currently on.
The easiest way would be to migrate this logic to Runnable and provide a callback:
class YourButchTask implements Runnable {
private WorkDoneCallback callback;
public YourButchTask(WorkDoneCallback callback) {
this.callback = callback;
}
@Override
public void run() {
CountDownLatch latch = new CountDownLatch(applicationInfoList.size);
for (ApplicationInfo info : applicationInfoList) {
service.execute(new MyTask(info, latch));
}
try {
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
//handle it
}
callback.workWasDone();
}
}
Afterward, you can submit your task to your service.
Note: your callback will be invoked from the executor thread, so you aren't allowed to access UI from it.
Here is a nice and simple tutorial, hopefully, that will help.
Update:
To be clear - Callback is your custom interface that will notify you when the work is done. Go ahead and use SAM, example:
interface WorkDoneCallback{
void workWasDone();
}
P.S. To redirect calls on main thread just use Handler with mainLooper under the hood, or runOnUiThread().