将回调代码迁移到暂停功能

Plo*_*kko 2 android suspend kotlin kotlin-coroutines

我正在使用协程将我的Android代码从Java重构为Kotlin,但是我没有找到一种简便的方法将基于回调的代码重写为暂停的函数。

一个基本的示例是返回结果的警报弹出窗口,在Javascript中将是这样的:

let value = prompt("please insert a value")
console.log("Value:"+value)
Run Code Online (Sandbox Code Playgroud)

我会在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)
        }
        //...
    }
}
Run Code Online (Sandbox Code Playgroud)

解析是我这个purpuse开发的定制功能,这里的源代码:

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
}
Run Code Online (Sandbox Code Playgroud)

我使用lambda和信号量快速开发了可解决的功能(请记住这是一个快速草稿),但是我不知道是否存在任何预先存在的功能(我找不到任何功能),是否可以对其进行优化或存在任何缺陷/问题。

谢谢。

Rom*_*rov 5

看来您正在尝试重新发明suspendCoroutine功能。我建议将您的resolvable函数替换为,suspendCoroutine以获取您正在寻找的功能:

    //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)
    }
Run Code Online (Sandbox Code Playgroud)

如果您在suspendCoroutine块周围执行“提取功能”重构并命名结果为暂停功能prompt,则可以用与JS非常相似的样式编写代码。

您也可以考虑使用suspendCancellebleCoroutine而不是Plain suspendCoroutine。这样,您可以支持取消启动的协同程序,并安装处理程序以在对话框取消时关闭对话框。