Android 正在等待侦听器冻结应用程序?

Android waiting for listener freezing the app?

我想显示一个进度对话框,并在 onCompleteListener 响应如下后关闭它:

class DialogSubjectsAdd: DialogFragment() {

    private val db = FirebaseFirestore.getInstance().collection("courses")
    private var docFetched = false
    private var processCompleted = false

    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
        super.onCreateDialog(savedInstanceState)

        getCoursesIndexDoc()
        // show progress dialog

        // wait until download operation is completed
        while (!processCompleted) {}
        // dismiss dialog

        // todo

    }

    private fun getCoursesIndexDoc() {
        // fetch the index document
        db.document("all")
            .get()
            .addOnCompleteListener { task ->
                if (task.isSuccessful) {
                    docFetched = true
                }
                processCompleted = true
            }
    }

}

但是上面的代码冻结了应用程序。

如果我评论 while 循环并将对话框代码关闭为:

// while (!processCompleted) {}
// // dismiss dialog

进度对话框永远显示。

那么,为什么 while 循环会冻结应用程序?

即使 processCompleted 的值永远不会变成 true,我认为它应该导致进度条永远 运行 而不是冻结应用程序。

但是由于 while 循环,即使进度 dialog 也没有显示,并且显示 dialog 的按钮仍然被点击并且应用程序被冻结,为什么?

那是因为 onCreateDialog 在系统的 UI 线程上运行 - 这意味着 UI 无法更新,而 运行。

解决方案是将关闭对话框的代码移至单独的线程 - 您的完成侦听器似乎是完美的地方!

override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
    super.onCreateDialog(savedInstanceState)

    getCoursesIndexDoc()
    // Don't do anything else here!
}

private fun getCoursesIndexDoc() {
    // fetch the index document
    db.document("all")
        .get()
        .addOnCompleteListener { task ->
            if (task.isSuccessful) {
                docFetched = true
            }
            // Instead of setting the flag, dismiss the dialog here
        }
}