What I want to do is to use kotlin coroutines for database operations and show users a loading screen in the meantime. My basic implementation is as follows:
fun loadSomeData(){
mainCoroutineScope.launch {
showLoadingDialog()
// suspening function over Dispatchers.IO, returns list
val dataList = fetchDataFromDatabase()
inflateDataIntoViews(dataList)
hideLoadingDialog()
}
}
This works perfectly for me when the loading takes quite some time for large datasets. But in scenarios where the fetchDataFromDatabase()
finishes quickly, showing and hiding the dialog box in quick succession creates an annoying glitching effect.
So what I want is to show the dialog box only if the fetchDataFromDatabase()
function take more than, lets say, 100 ms to complete.
So my question is, what is the performance efficient way to achieve this using kotlin coroutines?
Here's an idea:
fun loadSomeData(){
mainCoroutineScope.launch {
val dialogJob = launch {
delay(1000)
try {
showLoadingDialog()
coroutineContext.job.join()
} finally {
hideLoadingDialog()
}
}
val dataList = fetchDataFromDatabase()
inflateDataIntoViews(dataList)
dialogJob.cancel()
}
}
When you cancel the dialogJob
, it should either hit the delay
statement and prevent showing the dialog, or the join
statement, which will cause the finally
block to execute and hide it.
Here is how I have achieved this, without using !!
not null operator:
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)
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With