はじめに
タイトルの通りAndroid 11にて、AsyncTaskがdeprecatedになってしまったので、今回は呼び出し元になるべく影響を与えないように、Android 11対応を行っていきたいと思います。
基本的な対応
以下のようなAsyncTaskがあるとします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | class sampleAsyncTask extends AsyncTask<Void, Void, String> { sampleAsyncTask() { } @Override protected void onPreExecute() { } @Override protected String doInBackground(Void... void) { } @Override protected void onPostExecute(String result) { } } |
これを置き換えて行きます。
対応後のサンプル
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | class sampleAsyncTask { private class AsyncRunnable implements Runnable { private String result; Handler handler = new Handler(Looper.getMainLooper()); @Override public void run() { onPreExecute(); result = doInBackground(); handler.post(new Runnable() { @Override public void run() { onPostExecute(result); } }); } } public void execute() { ExecutorService executorService = Executors.newSingleThreadExecutor(); executorService.submit(new AsyncRunnable()); } void onPreExecute() { } String doInBackground() { } void onPostExecute(String result) { } } |
基本的にはRunnableクラスを作成しExecutorServiceで起動するようにします。呼び出し元に影響を与えないようにexecuteメソッドを用意しRunnableを呼び出します。AsyncTask同様に、onPreExecute、doInBackground、onPostExecuteの順番で呼び出されるようにします。一つ注意をするならば、以下のようにHandlerの宣言もdeprecatedされているので気をつけるようにしてください。
1 2 3 4 | // deprecated //Handler handler = new Handler(); Handler handler = new Handler(Looper.getMainLooper()); |
また、onPostExecuteをHandler内で呼び出しているのは、UIの更新をかけることを想定しています。
cancelとonCancelled
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | class sampleAsyncTask { boolean canceled; private class AsyncRunnable implements Runnable { private String result; Handler handler = new Handler(Looper.getMainLooper()); @Override public void run() { onPreExecute(); result = doInBackground(); handler.post(new Runnable() { @Override public void run() { if (!canceled) { onPostExecute(); } else { onCancelled(); } } }); } } public void execute() { ExecutorService executorService = Executors.newSingleThreadExecutor(); executorService.submit(new AsyncRunnable()); } void onPreExecute() { } String doInBackground() { cancel(true); } void onPostExecute(String result) { } void cancel(Boolean flag) { canceled = flag; } void onCancelled() { } } |
doInBackground内で何かあったときに、AsyncTaskのcancelを使用するパターンがあると思いますので、今回はこのようにサンプルを用意させてもらいました。AsyncTaskの処理の流れと同様に、cancelされた時はonPostExecuteではなく、onCancelledを呼ぶようにしています。
execute().get()への対応
AsyncTaskを使用しているときに、処理の終了を待つためにexecute().get()を使用することもあると思います。Runnableクラスでは戻り値を返せないので、この場合はCallableクラスを使用します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | class sampleAsyncTask { private class AsyncCallable implements Callable<String> { @Override public String call() throws Exception { String result = doInBackground(); return result; } } public String execute() { ExecutorService executorService = Executors.newSingleThreadExecutor(); try { return executorService.submit(newAsyncCallable()).get(); } catch (ExecutionException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } return null; } String doInBackground() { } } |
サンプルではCallableクラスを使用し、Stringを返却するように作成しました。ExecutorServiceのgetを使用することで、処理の終了まで待つことができるようになります。
最後に
deprecatedになったとはいえ、まだすぐに使えなくなるわけではないですが、今後のためにメンテナンスはしていきたいと思います。