非同期タスクの極めて簡単な処理

1249 ワード

使用例
var req = UserPublic.LoginReq.newBuilder().setEmail(email).setPassword(password).build()
val method = UserGrpc.newBlockingStub(MockConfig.channel)::login
asyncTask(req, method) {
    showUserInfo(it)
}

実装メカニズム:汎用メソッド+高次関数
fun  asyncTask(req: Req, function: (Req) -> Resp?, errorHandler: (Throwable) -> Any = SystemConfig.defaultErrorHandler, consumer: (Resp?) -> Any) {
    val errorHandler = CoroutineExceptionHandler { _, exception ->
        errorHandler.invoke(exception)
    }
    launch(errorHandler) {
        var resp = async(Dispatchers.IO) {
            function.invoke(req)
        }.await()
        consumer.invoke(resp)
    }
}

デフォルトのエラー処理がありますが、エラー処理をカスタマイズすることもできます.デフォルトでは、エラーを印刷するだけで、errorHandlerパラメータを自分で書き換えることができます.
class SystemConfig {
    companion object {
        val defaultErrorHandler: (Throwable) -> Any = { exception ->
            {
                LogUtils.print("Caught $exception")
            }
        }
    }
}

メリット
  • ビジネスコードとテンプレートコードを分離することで、後でコネを使わなくても、他のスレッドスケジューリングフレームワーク
  • に容易に切り替えることができる.
  • 後期拡張が容易で、現在のテンプレートコードはスレッド切替を行っただけで、後でロード進捗バーの表示と非表示など
  • を加えることができます.