我正在使用协程将我的 Android 代码从 Java 重构为 Kotlin,但我没有找到将基于回调的代码重写为挂起函数的简单方法。
一个基本的例子是一个返回结果的警告弹出窗口,在 Javascript 中它是这样的:
let value = prompt("please insert a value")
console.log("Value:"+value)
我会用 Kotlin 翻译成类似这样的东西:
class MainActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
//Standard activity initialization
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//Actual code...
launch {
val value = resolvable<String>(UI) { success, error ->
//Build a simple popup prompt with AlertDialog
val input = EditText(this@MainActivity)
val builder = AlertDialog.Builder(this@MainActivity)
.setTitle("please insert a value")
.setView(input)
.setPositiveButton("Ok",{ dialog, id ->
success(input.text.toString())//This lambda returns the value
})
val dialog = builder.create()
dialog.show()
}
println("Value:"+ value)
}
//...
}
}
resolvable 是我为此目的开发的自定义函数,这里是源代码:
import kotlinx.coroutines.experimental.DefaultDispatcher
import kotlinx.coroutines.experimental.cancelAndJoin
import kotlinx.coroutines.experimental.launch
import java.util.concurrent.Semaphore
import kotlin.coroutines.experimental.CoroutineContext
suspend fun <T> resolvable(
context: CoroutineContext = DefaultDispatcher,
block: suspend (success:(T?)->Unit,error:(Throwable)->Unit) -> Unit
):T?{
var result:T? = null
var exception:Throwable? = null
val semaphore = Semaphore(0)
val job = launch(context){
block({r:T? -> {
result=r
semaphore.release()
}},{e:Throwable -> {
exception=e
semaphore.release()
}})
}
semaphore.acquire()
job.cancelAndJoin()
if(exception!=null)
throw exception!!
return result
}
我使用 lambda 和信号量快速开发了 resolvable 函数(请记住这是一个快速草稿),但我不知道是否有任何预先存在的函数(我找不到)或者可以优化或有任何缺点/问题。
谢谢。
最佳答案
看来您正在尝试重新发明 suspendCoroutine
函数。我建议用 suspendCoroutine
的调用替换你的 resolvable
函数以获得你正在寻找的那种功能:
//Actual code...
launch(UI) {
val value = suspendCoroutine<String> { cont ->
//Build a simple popup prompt with AlertDialog
val input = EditText(this@MainActivity)
val builder = AlertDialog.Builder(this@MainActivity)
.setTitle("please insert a value")
.setView(input)
.setPositiveButton("Ok",{ dialog, id ->
cont.resume(input.text.toString()) //!!! Resume here
})
val dialog = builder.create()
dialog.show()
}
println("Value:"+ value)
}
如果围绕 suspendCoroutine
block 执行“提取函数”重构并将生成的挂起函数命名为 prompt
,那么您可以以非常类似于以下的样式编写代码JS.
您还可以考虑使用 suspendCancellebleCoroutine
而不是普通的 suspendCoroutine
。这样您就可以支持取消已启动的协程并安装一个处理程序以在取消时关闭您的对话框。
关于android - 将回调代码迁移到挂起的函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48379058/