#android #asynchronous #callback #kotlin-coroutines #android-livedata
Вопрос:
Программирование приложений для Android:
Итак, допустим, я запускаю асинхронную задачу в блоке onResume() моего фрагмента, в котором по завершении есть 2 метода обратного вызова Java — onSuccess() и OnFailure(). Между тем, на экране есть кнопка, которую пользователь может нажать в любое время. Загвоздка в том, что при нажатии кнопки мне нужно дождаться завершения предыдущей асинхронной задачи, прежде чем выполнять код нажатия кнопки.
Мне нужно показать индикатор выполнения при нажатии кнопки во время завершения асинхронной задачи (если она еще не завершена), но я не уверен, как ее закодировать, чтобы при нажатии кнопки я знал, что кнопка была нажата, а также асинхронная задача еще не завершена, и мне нужно дождаться ее завершения, прежде чем продолжить.
Я думаю, что в этом процессе мне нужно использовать сопрограммы LiveData и/или Kotlin, но я не уверен, как это сделать.
Может ли кто-нибудь, пожалуйста, направить меня в правильном направлении в этом вопросе? Я изо всех сил стараюсь понять асинхронное программирование.
Ответ №1:
Если вы не используете сопрограммы и т. Д. прямо сейчас вы можете легко реализовать это с помощью всего нескольких логических значений и «если». Предполагая , что все onSuccess()
onFailure()
и onBtnClick()
вызываются в основном потоке, это должно сработать:
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()
}
}
Вам также следует подумать о других угловых случаях, например: первая задача была запланирована, когда она уже запущена; кнопка нажата во время выполнения второй задачи и т. Д.
Ответ №2:
Определите a lateinit var
в верхней части вашего 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
}
Имейте в виду, что lifecycleScope
поток по умолчанию является основным, если вы хотите, чтобы сопрограмма выполнялась в фоновом потоке, предоставьте launch(dispatcher) {...}
функции соответствующий диспетчер.
Если вы используете а Fragment
вместо а Activity
, используйте viewLifecycleOwner.lifecycleScope.launch
вместо lifecycleScope.launch
lifecycleScope
является функцией расширения и может быть найдена в androidx.lifecycle:lifecycle-runtime-ktx:version
Комментарии:
1. Спасибо вам за решение. Я думаю, есть ли лучшее решение для цикла while в методе onButtonClicked ()?