android - 将回调代码迁移到挂起的函数

标签 android kotlin suspend kotlin-coroutines

我正在使用协程将我的 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/

相关文章:

android - 输入文字为白色

android - 在 Android VideoView 中显示 mp4 视频

android - Kotlin 中的 DialogFragment.onDismiss() 空指针异常

java - Hibernateflush()影响事务

string - 拆分函数 Kotlin 如何使用多个拆分参数

android - 用自己的 Intent 处理 Linkify onClick 事件

android - Android 上使用 DataBinding 或 RxJava 的 MVVM?

android - 如何从 google play 开发者控制台中删除暂停的应用程序?

android - 挂起函数后不执行非挂起函数

task - 是否可以在异步 python 中挂起和重新启动任务?