I've written a class, a series of instances of which are intended to be called from an AsyncTask, which will return a result from the method runReport(). It creates a worker thread just fine, but for some reason it then doesn't execute the Callable's call() method. What am I doing wrong?
//Problem: doStuff() never gets called, even though the worker thread gets created.
@Override
public ReportResult runReport() throws InterruptedException, ExecutionException {
Callable<ReportResult> report = new Callable<ReportResult>() {
@Override
public ReportResult call() throws Exception {
doStuff();
...
return new ReportResult(varWrittenByMethod);
}
};
FutureTask<ReportResult> result = new FutureTask<ReportResult>(report);
//I tried a few of these ExecutorService factory methods, with the same result.
//I only made my own ThreadFactory to verify the worker was created
ExecutorService es = Executors.newSingleThreadExecutor(new ThreadFact());
es.submit(report);
ReportResult finalResult = result.get();
es.shutdownNow();
return finalResult;
}
private class ThreadFact implements ThreadFactory{
@Override
public Thread newThread(Runnable r) {
Log.d(TAG, "Created worker Thread");
return new Thread(r);
}
}
As far as I can tell, I have to do this as a FutureTask in its own Thread, because it needs to do the following (all of which apart from the return is inside doStuff() ):
I'm open to better ways to do this. I originally let the AsyncTask make this call, then ran Looper.loop() on its thread, but I couldn't process a queue of these objects since I needed to call Looper.myLooper.quit() from the listener before returning a result, which poisoned the thread's message queue irreversibly.
Your thread factory doesn't propagate the passed Runnable to the created thread. In your ThreadFactory, try:
return new Thread(r);
Also, you should be using the FutureTask returned by the submit method, not the one you created explicitly. E.g.
FutureTask<ReportResult> result = es.submit(report);
ReportResult finalResult = result.get();