171d7c3bcf0400e4b81109dd785187e1a93da3cabChristian Williamspackage com.xtremelabs.robolectric.shadows; 271d7c3bcf0400e4b81109dd785187e1a93da3cabChristian Williams 371d7c3bcf0400e4b81109dd785187e1a93da3cabChristian Williamsimport android.os.AsyncTask; 471d7c3bcf0400e4b81109dd785187e1a93da3cabChristian Williamsimport android.os.ShadowAsyncTaskBridge; 571d7c3bcf0400e4b81109dd785187e1a93da3cabChristian Williamsimport com.xtremelabs.robolectric.Robolectric; 622c22c9aa4ca68c2deac6164edc1d82bc9645310Christian Williams & Phil Goodwinimport com.xtremelabs.robolectric.internal.Implementation; 722c22c9aa4ca68c2deac6164edc1d82bc9645310Christian Williams & Phil Goodwinimport com.xtremelabs.robolectric.internal.Implements; 822c22c9aa4ca68c2deac6164edc1d82bc9645310Christian Williams & Phil Goodwinimport com.xtremelabs.robolectric.internal.RealObject; 971d7c3bcf0400e4b81109dd785187e1a93da3cabChristian Williams 10cdc28f1a2d605ebc0ad6ea19251718602480a393Joe Moore & Tyler Schultzimport java.util.concurrent.Callable; 11cdc28f1a2d605ebc0ad6ea19251718602480a393Joe Moore & Tyler Schultzimport java.util.concurrent.CancellationException; 12cdc28f1a2d605ebc0ad6ea19251718602480a393Joe Moore & Tyler Schultzimport java.util.concurrent.ExecutionException; 13cdc28f1a2d605ebc0ad6ea19251718602480a393Joe Moore & Tyler Schultzimport java.util.concurrent.FutureTask; 14cdc28f1a2d605ebc0ad6ea19251718602480a393Joe Moore & Tyler Schultzimport java.util.concurrent.TimeUnit; 15cdc28f1a2d605ebc0ad6ea19251718602480a393Joe Moore & Tyler Schultzimport java.util.concurrent.TimeoutException; 16cdc28f1a2d605ebc0ad6ea19251718602480a393Joe Moore & Tyler Schultz 1771d7c3bcf0400e4b81109dd785187e1a93da3cabChristian Williams@Implements(AsyncTask.class) 1871d7c3bcf0400e4b81109dd785187e1a93da3cabChristian Williamspublic class ShadowAsyncTask<Params, Progress, Result> { 198d84df659ff5bf89d11256618a5e4c5f08cc15eaNeil Traft 20f98fe60b10305335ff39a2dd6ab04948e9fc83f7Jan Berkel @RealObject private AsyncTask<Params, Progress, Result> realAsyncTask; 218ac50c8ceba6b4a4464a2e6619a3f06cbcd702c1Wenhui Yao 22f98fe60b10305335ff39a2dd6ab04948e9fc83f7Jan Berkel private final FutureTask<Result> future; 23f98fe60b10305335ff39a2dd6ab04948e9fc83f7Jan Berkel private final BackgroundWorker worker; 24f98fe60b10305335ff39a2dd6ab04948e9fc83f7Jan Berkel private AsyncTask.Status status = AsyncTask.Status.PENDING; 258ac50c8ceba6b4a4464a2e6619a3f06cbcd702c1Wenhui Yao 268d84df659ff5bf89d11256618a5e4c5f08cc15eaNeil Traft public ShadowAsyncTask() { 278d84df659ff5bf89d11256618a5e4c5f08cc15eaNeil Traft worker = new BackgroundWorker(); 288d84df659ff5bf89d11256618a5e4c5f08cc15eaNeil Traft future = new FutureTask<Result>(worker) { 298d84df659ff5bf89d11256618a5e4c5f08cc15eaNeil Traft @Override 308d84df659ff5bf89d11256618a5e4c5f08cc15eaNeil Traft protected void done() { 31f98fe60b10305335ff39a2dd6ab04948e9fc83f7Jan Berkel status = AsyncTask.Status.FINISHED; 328d84df659ff5bf89d11256618a5e4c5f08cc15eaNeil Traft try { 338d84df659ff5bf89d11256618a5e4c5f08cc15eaNeil Traft final Result result = get(); 348d84df659ff5bf89d11256618a5e4c5f08cc15eaNeil Traft Robolectric.getUiThreadScheduler().post(new Runnable() { 358d84df659ff5bf89d11256618a5e4c5f08cc15eaNeil Traft @Override public void run() { 368d84df659ff5bf89d11256618a5e4c5f08cc15eaNeil Traft getBridge().onPostExecute(result); 378d84df659ff5bf89d11256618a5e4c5f08cc15eaNeil Traft } 388d84df659ff5bf89d11256618a5e4c5f08cc15eaNeil Traft }); 398d84df659ff5bf89d11256618a5e4c5f08cc15eaNeil Traft } catch (CancellationException e) { 408d84df659ff5bf89d11256618a5e4c5f08cc15eaNeil Traft Robolectric.getUiThreadScheduler().post(new Runnable() { 418d84df659ff5bf89d11256618a5e4c5f08cc15eaNeil Traft @Override public void run() { 428d84df659ff5bf89d11256618a5e4c5f08cc15eaNeil Traft getBridge().onCancelled(); 438d84df659ff5bf89d11256618a5e4c5f08cc15eaNeil Traft } 448d84df659ff5bf89d11256618a5e4c5f08cc15eaNeil Traft }); 458d84df659ff5bf89d11256618a5e4c5f08cc15eaNeil Traft } catch (InterruptedException e) { 468d84df659ff5bf89d11256618a5e4c5f08cc15eaNeil Traft // Ignore. 478d84df659ff5bf89d11256618a5e4c5f08cc15eaNeil Traft } catch (Throwable t) { 488d84df659ff5bf89d11256618a5e4c5f08cc15eaNeil Traft throw new RuntimeException("An error occured while executing doInBackground()", 49277acc162389794a49c28b241b5591df63c4d637Jon Boekenoogen t); 508d84df659ff5bf89d11256618a5e4c5f08cc15eaNeil Traft } 518d84df659ff5bf89d11256618a5e4c5f08cc15eaNeil Traft } 528d84df659ff5bf89d11256618a5e4c5f08cc15eaNeil Traft }; 538d84df659ff5bf89d11256618a5e4c5f08cc15eaNeil Traft } 5471d7c3bcf0400e4b81109dd785187e1a93da3cabChristian Williams 558d84df659ff5bf89d11256618a5e4c5f08cc15eaNeil Traft @Implementation 568d84df659ff5bf89d11256618a5e4c5f08cc15eaNeil Traft public boolean isCancelled() { 578d84df659ff5bf89d11256618a5e4c5f08cc15eaNeil Traft return future.isCancelled(); 588d84df659ff5bf89d11256618a5e4c5f08cc15eaNeil Traft } 5971d7c3bcf0400e4b81109dd785187e1a93da3cabChristian Williams 60c357b8918be524c83f806119eb4aead2259a9ef6Phil Goodwin & Tyler Schultz @Implementation 6171d7c3bcf0400e4b81109dd785187e1a93da3cabChristian Williams public boolean cancel(boolean mayInterruptIfRunning) { 628d84df659ff5bf89d11256618a5e4c5f08cc15eaNeil Traft return future.cancel(mayInterruptIfRunning); 6371d7c3bcf0400e4b81109dd785187e1a93da3cabChristian Williams } 6471d7c3bcf0400e4b81109dd785187e1a93da3cabChristian Williams 65cdc28f1a2d605ebc0ad6ea19251718602480a393Joe Moore & Tyler Schultz @Implementation 668d84df659ff5bf89d11256618a5e4c5f08cc15eaNeil Traft public Result get() throws InterruptedException, ExecutionException { 678d84df659ff5bf89d11256618a5e4c5f08cc15eaNeil Traft return future.get(); 688d84df659ff5bf89d11256618a5e4c5f08cc15eaNeil Traft } 6971d7c3bcf0400e4b81109dd785187e1a93da3cabChristian Williams 70cdc28f1a2d605ebc0ad6ea19251718602480a393Joe Moore & Tyler Schultz @Implementation 718d84df659ff5bf89d11256618a5e4c5f08cc15eaNeil Traft public Result get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { 728d84df659ff5bf89d11256618a5e4c5f08cc15eaNeil Traft return future.get(timeout, unit); 738d84df659ff5bf89d11256618a5e4c5f08cc15eaNeil Traft } 7471d7c3bcf0400e4b81109dd785187e1a93da3cabChristian Williams 75c357b8918be524c83f806119eb4aead2259a9ef6Phil Goodwin & Tyler Schultz @Implementation 768d84df659ff5bf89d11256618a5e4c5f08cc15eaNeil Traft public AsyncTask<Params, Progress, Result> execute(final Params... params) { 77f98fe60b10305335ff39a2dd6ab04948e9fc83f7Jan Berkel status = AsyncTask.Status.RUNNING; 786b3f26530e07e46c5c79d37a3cdeb3856f9339cdChristian Williams getBridge().onPreExecute(); 798cb1d30709655f11542120d321f1293954a70d96Jan Berkel 808d84df659ff5bf89d11256618a5e4c5f08cc15eaNeil Traft worker.params = params; 8171d7c3bcf0400e4b81109dd785187e1a93da3cabChristian Williams 820fe1965a36c508fb5b9fa4c8d0caa2d30540f2ccChristian Williams & Phil Goodwin Robolectric.getBackgroundScheduler().post(new Runnable() { 8371d7c3bcf0400e4b81109dd785187e1a93da3cabChristian Williams @Override public void run() { 848d84df659ff5bf89d11256618a5e4c5f08cc15eaNeil Traft future.run(); 8571d7c3bcf0400e4b81109dd785187e1a93da3cabChristian Williams } 8671d7c3bcf0400e4b81109dd785187e1a93da3cabChristian Williams }); 878cb1d30709655f11542120d321f1293954a70d96Jan Berkel 888cb1d30709655f11542120d321f1293954a70d96Jan Berkel return realAsyncTask; 8971d7c3bcf0400e4b81109dd785187e1a93da3cabChristian Williams } 9071d7c3bcf0400e4b81109dd785187e1a93da3cabChristian Williams 91f98fe60b10305335ff39a2dd6ab04948e9fc83f7Jan Berkel @Implementation 92f98fe60b10305335ff39a2dd6ab04948e9fc83f7Jan Berkel public AsyncTask.Status getStatus() { 93f98fe60b10305335ff39a2dd6ab04948e9fc83f7Jan Berkel return status; 94f98fe60b10305335ff39a2dd6ab04948e9fc83f7Jan Berkel } 95f98fe60b10305335ff39a2dd6ab04948e9fc83f7Jan Berkel 966b3f26530e07e46c5c79d37a3cdeb3856f9339cdChristian Williams /** 976b3f26530e07e46c5c79d37a3cdeb3856f9339cdChristian Williams * Enqueue a call to {@link AsyncTask#onProgressUpdate(Object[])} on UI looper (or run it immediately 986b3f26530e07e46c5c79d37a3cdeb3856f9339cdChristian Williams * if the looper it is not paused). 996b3f26530e07e46c5c79d37a3cdeb3856f9339cdChristian Williams * 1006b3f26530e07e46c5c79d37a3cdeb3856f9339cdChristian Williams * @param values The progress values to update the UI with. 1016b3f26530e07e46c5c79d37a3cdeb3856f9339cdChristian Williams * @see AsyncTask#publishProgress(Object[]) 1026b3f26530e07e46c5c79d37a3cdeb3856f9339cdChristian Williams */ 1036b3f26530e07e46c5c79d37a3cdeb3856f9339cdChristian Williams @Implementation 1046b3f26530e07e46c5c79d37a3cdeb3856f9339cdChristian Williams public void publishProgress(final Progress... values) { 1056b3f26530e07e46c5c79d37a3cdeb3856f9339cdChristian Williams Robolectric.getUiThreadScheduler().post(new Runnable() { 1066b3f26530e07e46c5c79d37a3cdeb3856f9339cdChristian Williams @Override public void run() { 1076b3f26530e07e46c5c79d37a3cdeb3856f9339cdChristian Williams getBridge().onProgressUpdate(values); 1086b3f26530e07e46c5c79d37a3cdeb3856f9339cdChristian Williams } 1096b3f26530e07e46c5c79d37a3cdeb3856f9339cdChristian Williams }); 1106b3f26530e07e46c5c79d37a3cdeb3856f9339cdChristian Williams } 1116b3f26530e07e46c5c79d37a3cdeb3856f9339cdChristian Williams 1126b3f26530e07e46c5c79d37a3cdeb3856f9339cdChristian Williams private ShadowAsyncTaskBridge<Params, Progress, Result> getBridge() { 1136b3f26530e07e46c5c79d37a3cdeb3856f9339cdChristian Williams return new ShadowAsyncTaskBridge<Params, Progress, Result>(realAsyncTask); 1146b3f26530e07e46c5c79d37a3cdeb3856f9339cdChristian Williams } 1158cb1d30709655f11542120d321f1293954a70d96Jan Berkel 1168d84df659ff5bf89d11256618a5e4c5f08cc15eaNeil Traft private final class BackgroundWorker implements Callable<Result> { 1178d84df659ff5bf89d11256618a5e4c5f08cc15eaNeil Traft Params[] params; 1188d84df659ff5bf89d11256618a5e4c5f08cc15eaNeil Traft @Override 1198d84df659ff5bf89d11256618a5e4c5f08cc15eaNeil Traft public Result call() throws Exception { 1208d84df659ff5bf89d11256618a5e4c5f08cc15eaNeil Traft return getBridge().doInBackground(params); 1218d84df659ff5bf89d11256618a5e4c5f08cc15eaNeil Traft } 1228d84df659ff5bf89d11256618a5e4c5f08cc15eaNeil Traft } 12371d7c3bcf0400e4b81109dd785187e1a93da3cabChristian Williams} 124