I've been downloading and parsing a webpage with Jsoup, to show the content in a list. This process takes a while so I implemented Callable interface to do the task in another thread and get the result back. The problem is that it still blocks UI during the process.
public class GetListaNotizie implements Callable<ArrayList<Notizia>> {
static ArrayList<Notizia> getNotizieBySezione() {
[...] Long process
return notizie;
}
@Override
public ArrayList<Notizia> call() throws Exception {
return getNotizieBySezione();
}
}
And then:
final ExecutorService service;
final Future<ArrayList<Notizia>> task;
service = Executors.newFixedThreadPool(1);
task = service.submit(new GetListaNotizie());
try {
ArrayList<Notizia> notizie = task.get();
lvListaNotizie.setAdapter(new RiempiLista(activity, notizie));
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
What am I missing?
Because ... you're submitting your
Callable
to the pool, then explicitly blocking the thread waiting for it to finish.I missed the Android tag on your Q. You're re-inventing the wheel here. Android provides
AsyncTask
for exactly this use case. See the AsyncTask example under Processes and Threads for an example of how it works.(original answer follows)
You need your
Callable
to update/notify the UI when it's finished. One possible approach would be to pass a reference to the list you mention to yourCallable
.Edit to add from comments:
Right now, you submit your
Callable
to the pool. Then you sit there waiting for it to finish (blocking the UI thread). Then you do this:Pass
lvListaNotizie
to yourGetListaNotizie
via a constructor and have that happen at the end ofcall()
instead of returning the list to theFuture
. I don't know whatlvListaNotizie
is; if it's not thread-safe you will want to synchronize on it.