使用协程封装异步操作
private suspend fun showDialog(context: Activity): Boolean {
return suspendCoroutine {
val builder = AlertDialog.Builder(context)
builder.setTitle("问题:")
builder.setMessage("请问你满十八岁了吗?")
builder.setIcon(R.mipmap.ic_launcher_round)
builder.setCancelable(true)
builder.setPositiveButton("是的") { dialog, which ->
dialog.dismiss()
it.resume(true)
}
builder.setNegativeButton("不是") { dialog, which ->
dialog.dismiss()
it.resume(false)
}
builder.show()
}
}
如上所示,我们使用suspendCoroutine将异步的弹窗显示转换为同步的显示,只需要如下使用,则可以同步获取结果
launch {
val result = showDialog(this@MainActivity)
Toast.makeText(this@MainActivity, "result = ${result}", Toast.LENGTH_SHORT).show()
}
当然也可以抛出异常或者使用Result
it.resumeWithException(Exception()) //抛出异常
it.resumeWith(Result.success(false))//返回Result对象
it.resumeWith(Result.failure(Exception("")))//抛出异常
还有一个suspendCancellableCoroutine
,与suspendCoroutine
的区别为提供了一个cancel方法
private suspend fun showDialog(context: Activity): Boolean {
return suspendCancellableCoroutine {
val builder = AlertDialog.Builder(context)
builder.setTitle("问题:")
builder.setMessage("请问你满十八岁了吗?")
builder.setIcon(R.mipmap.ic_launcher_round)
builder.setCancelable(true)
builder.setPositiveButton("是的") { dialog, which ->
dialog.dismiss()
it.resume(true)
}
builder.setNegativeButton("不是") { dialog, which ->
dialog.dismiss()
//如果不传递,默认也是CancellationException,或者抛出其他异常
it.cancel(CancellationException("2333"))
}
builder.show()
}
}
协程异常处理
val handler = CoroutineExceptionHandler { _, exception ->
println("CoroutineExceptionHandler got $exception")
}
launch(handler){
}
Android中能使用的CoroutineScope
class MainActivity : AppCompatActivity() {
private val scope = MainScope()
override fun onDestroy() {
super.onDestroy()
scope.cancel()
}
}
倒计时
fun countDownCoroutines(
total: Int, onTick: (Int) -> Unit,
onFinish: () -> Unit,
scope: CoroutineScope = GlobalScope
): Job {
return flow {
for (i in total downTo 0) {
emit(i)
delay(1000)
}
}.flowOn(Dispatchers.Default)
.onCompletion {
if (it == null) onFinish()
}
.onEach { onTick(it) }
.flowOn(Dispatchers.Main)
.launchIn(scope)
}
超时
//会抛出TimeoutCancellationException,导致协程被取消
withTimeout(1300L) {
val startTime = System.currentTimeMillis()
repeat(1000) { i ->
println("[job] 运行: $i, 累积运行时间: ${System.currentTimeMillis() - startTime}毫秒")
delay(5000L)
}
}
//这一个不会抛出异常,会返回null
withTimeoutOrNull(1300L) {
val startTime = System.currentTimeMillis()
repeat(1000) { i ->
println("[job] 运行: $i, 累积运行时间: ${System.currentTimeMillis() - startTime}毫秒")
delay(5000L)
}
}