タイトルの通りAndroid 11にて、AsyncTaskがdeprecatedになってしまったので、今回は呼び出し元になるべく影響を与えないように、Android 11対応を行っていきたいと思います。
以下のようなAsyncTaskがあるとします。
class sampleAsyncTask extends AsyncTask<Void, Void, String> { sampleAsyncTask() { } @Override protected void onPreExecute() { } @Override protected String doInBackground(Void... void) { } @Override protected void onPostExecute(String result) { } }
これを置き換えて行きます。
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されているので気をつけるようにしてください。
// deprecated //Handler handler = new Handler(); Handler handler = new Handler(Looper.getMainLooper());
また、onPostExecuteをHandler内で呼び出しているのは、UIの更新をかけることを想定しています。
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を呼ぶようにしています。
AsyncTaskを使用しているときに、処理の終了を待つためにexecute().get()を使用することもあると思います。Runnableクラスでは戻り値を返せないので、この場合はCallableクラスを使用します。
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になったとはいえ、まだすぐに使えなくなるわけではないですが、今後のためにメンテナンスはしていきたいと思います。