以前の記事で、Android 11にてdeprecatedになったAsyncTask対応のjava編の記事を書きましたが、今回はそれのKotlin編になります。前回の記事はこちら。
以下のようなAsyncTaskがあるとします。
class sampleAsyncTask : AsyncTask<String, Void, String>() { override fun onPreExecute() { } override fun doInBackground(vararg param: String): String { return "" } override fun onPostExecute(result: String) { } }
これを置き換えて行きます。
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とは、Kotlin 1.3から正規にに導入された非同期処理を簡単に実装できる機能です。
AsyncTaskを使用せずにCoroutinesで実装する場合のサンプルを紹介したいと思います。
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を呼ぶときはこのようにして呼び出します。
val scope = CoroutineScope(Dispatchers.Default) scope.launch { sampleTask() } // 止めたいときは以下のように scope.coroutineContext.cancelChildren()
KotlinでAsyncTaskを使用しているケースはあまりないと思いますが、javaから移植だったり古いプロジェクトだとまだ見られるので、これを機にCoroutinesなどにリファクタリングしたいですね。