はじめに
以前の記事で、Android 11にてdeprecatedになったAsyncTask対応のjava編の記事を書きましたが、今回はそれのKotlin編になります。前回の記事はこちら。
基本的な対応
以下のようなAsyncTaskがあるとします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | class sampleAsyncTask : AsyncTask<String, Void, String>() { override fun onPreExecute() { } override fun doInBackground(vararg param: String): String { return "" } override fun onPostExecute(result: String) { } } |
これを置き換えて行きます。
対応後のサンプル
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 | class sampleAsyncTask { lateinit var strParams: String inner class AsyncRunnable : Runnable { private lateinit var result: String var handler = Handler(Looper.getMainLooper()) override fun run() { // ここにバックグラウンド処理を書く result = doInBackground() handler.post { onPostExecute(result) } } } fun execute(vararg params: String) { strParams = params[0] val executorService = Executors.newSingleThreadExecutor() executorService.submit(AsyncRunnable()) } fun doInBackground(str: String): String { return "" } fun onPostExecute(result: List<SetUpCorespondenceItem>) { } } |
基本的にはRunnableクラスを作成しExecutorServiceで起動するようにします。呼び出し元に影響を与えないようにexecuteメソッドを用意しRunnableを呼び出します。AsyncTask同様に、onPreExecute、doInBackground、onPostExecuteの順番で呼び出されるようにします。また、onPostExecuteをHandler内で呼び出しているのは、UIの更新をかけることを想定しています。
Coroutinesで実装
Coroutinesとは、Kotlin 1.3から正規にに導入された非同期処理を簡単に実装できる機能です。
AsyncTaskを使用せずにCoroutinesで実装する場合のサンプルを紹介したいと思います。
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 | private suspend fun sampleTask() { try { // onPreExecuteと同等の処理 withContext(Dispatchers.Main) { Log.d(localClassName, "始めます") } // doInBackgroundメソッドと同等の処理 Thread.sleep(800) for (i in 1..10) { //onProgressUpdateメソッドと同等の処理 withContext(Dispatchers.Main) { Log.d(localClassName, "ここでUIの更新") } Thread.sleep(800) } // onPostExecuteメソッドと同等の処理 withContext(Dispatchers.Main) { Log.d(localClassName, "終わります") } } catch (e: Exception) { // onCancelledメソッドと同等の処理 Log.e(localClassName, "ここにキャンセル時の処理を記述", e) } } |
sampleTaskを呼ぶときはこのようにして呼び出します。
1 2 3 4 5 6 7 8 | val scope = CoroutineScope(Dispatchers.Default) scope.launch { sampleTask() } // 止めたいときは以下のように scope.coroutineContext.cancelChildren() |
最後に
KotlinでAsyncTaskを使用しているケースはあまりないと思いますが、javaから移植だったり古いプロジェクトだとまだ見られるので、これを機にCoroutinesなどにリファクタリングしたいですね。