следующую ситуацию:
Есть предположим кнопка, при нажатию на которую запускается какой-то запрос на сервер через suspend функцию, и пока запрос идёт кнопка должна быть заблокирована как-то так:
val cs = rememberCoroutineScope()
var buttonEnabled by remember { mutableState(true) }
...
Button(onClick = {
buttonEnabled = false
cs.launch {
myService.callServer();
buttonEnabled = true
}
}, enabled = buttonEnabled )
Если, пока запрос на сервер выполняется, эта композ функция (с кнопкой и скоупом) выйдет из композиции скоуп будет убит и соответственно запрос на сервер будет отменён (по крайней мере частично). Для некоторых ситуаций такое поведение меня не устраивает - т.е. я не хочу чтобы запрос отменялся (особенно если он отменится до посылки на сервер потому что например callServer делает что-то до и это занимает достаточно времени чтобы элемент ушёл из композиции). Для этого я завёл специальный скоуп который живёт на уровне корневой компоуз функции и использую его:
val cs = mySpecialBackgroundScope
// val cs = rememberCoroutineScope()
Непонятно что будет происходить с после myService.callServer();
когда запрос завершится в то время когда функция уже вышла из композиции?
видимо ничего... отменится саспенд функция и всё
Я бы сделал немного по другому. Я бы сделал чтобы сервис запускал в себе функцию и возвращал бы job. А вы уже делайте job.join и потом включайте кнопку.
Сделал бы что? Чтобы сделать job.join мне в любом случае понадобится скоуп. Чтобы создать job внутри функции сервиса мне тоже нужен какой-то скоуп. Даже если я снаружи буду использовать скоуп из композа а внутри какой-то другой скоуп - это никак не отвечает на мой вопрос... точнее это настолько меняет условия задачи что вопрос теряет смысл :)
а нельзя это всё вынести на уровень вью модели? она работает с suspend функциями и отдаёт нужный стейт наружу через LiveData?
Да при чём тут это? Ну хорошо, предположим жизненный цикл вью модели привязан к навигации (т.е. уходит экран - убивают вью модель) - тот же самый вопрос, только теперь про вью модели :)
а если умер экран, есть ли смысл думать о кнопках на нём?)
Так речь не про кнопки а про взаимодействие с захваченными переменными. Если захвачен не булеан а что-то посложнее и что-то что завязано на компоуз - оно же не сможет отработать.
я не особо силён в компоузе, но кажется, что все запросы должны быть всё же во вью моделе, а из неё торчать наружу стейт и не будет никакого захвата переменных
в моём примере это не "запрос" - т.е. мне не нужны никакие данные от него, это операция что от неё должно торчать из вью модели?
так погоди, ты ведь делаешь обращение к myService и, когда он ответит, ты хочешь поменять состояние кнопки, сменить enabled?
так почему из вью модели на может торчать какой-то стейт а-ля State(val isButtonEnabled: Boolean), который ты обернёшь в LiveData и добавить метод во ViewModel, по типу class SomeViewModel : ViewModel() { private val state: MutableLiveData = ... val state: LiveData = ... fun onSomeButtonClicked() { state.value = state.value!!.copy(isButtonEnabled = false) scope.launch { ..... state.value = state.value!!.copy(isButtonEnabled = true) } }
Обсуждают сегодня