簡體   English   中英

如果 kotlin 協程作業需要相當長的時間才能完成,如何有效地顯示加載對話框?

[英]How to efficiently show loading dialog if kotlin coroutine job takes quite some time to complete?

我想做的是使用 kotlin 協程進行數據庫操作,同時向用戶顯示加載屏幕。 我的基本實現如下:

fun loadSomeData(){
    mainCoroutineScope.launch { 
        showLoadingDialog()
        // suspening function over Dispatchers.IO, returns list
        val dataList = fetchDataFromDatabase()
        inflateDataIntoViews(dataList)
        hideLoadingDialog()
    }
}

當加載大型數據集需要相當長的時間時,這對我來說非常有效。 但是在fetchDataFromDatabase()快速完成的情況下,快速連續顯示和隱藏對話框會產生煩人的故障效果。

所以我想要的是僅當fetchDataFromDatabase() function需要超過 100 毫秒才能完成時才顯示對話框。

所以我的問題是,使用 kotlin 協程實現這一目標的高效方法是什么?

這是一個想法:

fun loadSomeData(){
    mainCoroutineScope.launch {
        val dialogJob = launch {
            delay(1000)
            try {
                showLoadingDialog()
                coroutineContext.job.join()
            } finally {
                hideLoadingDialog()
            }
        }
        val dataList = fetchDataFromDatabase()
        inflateDataIntoViews(dataList)
        dialogJob.cancel()
    }
}

當您取消dialogJob時,它應該點擊delay語句並阻止顯示對話框,或者join語句,這將導致finally塊執行並隱藏它。

這是我在不使用的情況下實現這一目標的方法!! 不是 null 運算符:

val deferred = lifecycleScope.async(Dispatchers.IO) {
    // perform possibly long running async task here
}

lifecycleScope.launch (Dispatchers.Main){
    // delay showing the progress dialog for whatever time you want
    delay(100)

    // check if the task is still active
    if (deferred.isActive) {

        // show loading dialog to user if the task is taking time
        val progressDialogBuilder = createProgressDialog()

        try {
            progressDialogBuilder.show()

            // suspend the coroutine till deferred finishes its task
            // on completion, deferred result will be posted to the
            // function and try block will be exited.
            val result = deferred.await()
            onDeferredResult(result)

        } finally {
            // when deferred finishes and exits try block finally
            // will be invoked and we can cancel the progress dialog
            progressDialogBuilder.cancel()
        }
    } else {
        // if deferred completed already withing the wait time, skip
        // showing the progress dialog and post the deferred result
        val result = deferred.await()
        onDeferredResult(result)
    }
}

加載對話框的主要目的是防止用戶在加載時觸摸 UI,但不能保證這一點。 在對話框彈出之前,用戶總是有機會觸摸某個按鈕。

更好的方法是禁用或隱藏 UI 組件,或者通常顯示 UI 的“加載版本”。

最好讓用戶取消加載而不是設置一個短暫的超時,因此您可能仍然需要一個顯示取消按鈕的對話框或小吃欄,或者您可以在您的應用程序中創建一個任務管理器頁面,但這確實很復雜。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM