メソッド runReport() から結果を返す、AsyncTask から呼び出される一連のインスタンスのクラスを作成しました。ワーカー スレッドは正常に作成されますが、何らかの理由で Callable の call() メソッドが実行されません。私は何を間違っていますか?
//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);
}
}
私が知る限り、これは独自の Thread で FutureTask として実行する必要があります。これは、次のことを行う必要があるためです (戻り値以外はすべて doStuff() 内にあります)。
- いくつかの同期セットアップを実行します (AsyncTask はそれを UI スレッドから切り離します)。
- Looper.prepare() を呼び出す
- リスナーを登録する
- Looper.loop() を呼び出し、一定期間にわたってリスナーからいくつかのコールバックをキャッチします。
- 十分なデータポイントがある場合、リスナーのコールバック内で Looper.myLooper().quit() を呼び出します
- 結果を返す
私はこれを行うためのより良い方法を受け入れています。最初は AsyncTask にこの呼び出しを行わせてから、そのスレッドで Looper.loop() を実行しましたが、結果を返す前にリスナーから Looper.myLooper.quit() を呼び出す必要があったため、これらのオブジェクトのキューを処理できませんでした。 、スレッドのメッセージ キューを不可逆的に汚染しました。