package jp.juggler.subwaytooter.util import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import jp.juggler.subwaytooter.dialog.ProgressDialogEx import jp.juggler.util.LogCategory import jp.juggler.util.dismissSafe import jp.juggler.util.showToast import kotlinx.coroutines.* import kotlin.coroutines.CoroutineContext abstract class AsyncActivity : AppCompatActivity(), CoroutineScope { companion object { private val log = LogCategory("AsyncActivity") } private lateinit var job : Job override val coroutineContext : CoroutineContext get() = job + Dispatchers.Main override fun onCreate(savedInstanceState : Bundle?) { job = Job() super.onCreate(savedInstanceState) } override fun onDestroy() { super.onDestroy() (job + Dispatchers.Default).cancel() } fun runWithProgress( caption : String, doInBackground : suspend CoroutineScope.(ProgressDialogEx) -> T, afterProc : suspend CoroutineScope.(result : T) -> Unit = {}, progressInitializer : suspend CoroutineScope.(ProgressDialogEx) -> Unit = {}, preProc : suspend CoroutineScope.() -> Unit = {}, postProc : suspend CoroutineScope.() -> Unit = {} ) { val progress = ProgressDialogEx(this) val task = async(Dispatchers.IO) { doInBackground(progress) } launch { try { preProc() } catch(ex : Throwable) { log.trace(ex) } progress.setCancelable(true) progress.setOnCancelListener { task.cancel() } progress.isIndeterminateEx = true progress.setMessageEx("${caption}…") progressInitializer(progress) progress.show() try { val result = try { task.await() } catch(ex : CancellationException) { null } if(result != null) afterProc(result) } catch(ex : Throwable) { showToast(ex, "$caption failed.") } finally { progress.dismissSafe() try { postProc() } catch(ex : Throwable) { log.trace(ex) } } } } }