Android app programming:
So let's say I trigger an asynchronous task in the onResume() block of my fragment that has 2 Java callback methods on completion - onSuccess() and onFailure(). Meanwhile, there's a button on the screen that the user can click any time. The catch is, on button click I need to wait for the earlier asynchronous task to complete before executing button click code.
I need to show a progress bar on button click while the asynchronous task completes (if it hasn't completed already), but not sure how to code it such that on button click I am aware that the button has been clicked and also the async task hasn't completed yet and I need to wait for it to complete before proceeding further.
I am thinking I need to use LiveData and/or Kotlin coroutines in this process, but not sure how to proceed with it.
Can anyone please guide me in the right direction on this? I am trying my best to understand asynchronous programming.
CodePudding user response:
If you don't use coroutines, etc. right now then you can implement this easily with just a few booleans and ifs. Assuming all onSuccess()
, onFailure()
and onBtnClick()
are invoked on the main thread, this should do the trick:
private var firstTaskRunning = false
private var scheduledSecondTask = false
fun startFirstTask() {
firstTaskRunning = true
// start first task
}
fun onSuccess() {
onFirstTaskFinished()
}
fun onFailure() {
onFirstTaskFinished()
}
fun onFirstTaskFinished() {
firstTaskRunning = false
if (scheduledSecondTask) {
scheduledSecondTask = false
hideBtnProgress()
secondTask()
}
}
fun onBtnClick() {
if (firstTaskRunning) {
scheduledSecondTask = true
showBtnProgress()
} else {
secondTask()
}
}
You should also think about other corner cases like for example: first task was scheduled while it is already running; button is clicked while second task is running, etc.
CodePudding user response:
Define a lateinit var
at the top of your Activity
, private lateinit var asyncJob: Job
override fun onResume() {
super.onResume()
asyncJob = lifecycleScope.launch {
// Do the work
}
}
fun onButtonClicked() {
while (asyncJob.isActive) showProgressIndicator()
hideProgressIndicator()
// Handle the button click
}
Keep in mind that lifecycleScope
's default thread is main, if you want a coroutine to run on a background thread, provide an adequate dispatcher to the launch(dispatcher) {...}
function.
If you're using a Fragment
instead of an Activity
use viewLifecycleOwner.lifecycleScope.launch
instead of lifecycleScope.launch
lifecycleScope
is an extension function and can be found in androidx.lifecycle:lifecycle-runtime-ktx:version