Пишу логику сетевых запросов с использованием корутин.
В корутинах слабо шарю, написал в итоге какую - то дичь(пусть и работающую), и сейчас логика похода в сеть выглядит так(обобщённо):
Вью просит VM чего - нибудь загрузить -> VM открывает viewModelScope и дёргает у интерактора suspend функцию, которая возвращает результат -> suspend функция вызывает suspend функцию у репозитория -> репозиторий дёргает suspend функцию у ретрофита, и либо возвращает данные, либо кидает Exception.
Проблему я понял поздно: у меня в интеракторе 20 функций, из них 18 - suspend. Получилось месиво адовое. Если я захочу добавить в интерактор новую функцию, которая будет использовать результат другой функции из интерактора, то мне придётся для новой функции писать suspend модификатор, даже если это идеологически не нужно. Гг wp.
Думаю над тем как это всё по человечески переписать.
Пока придумал вот что: не открывать никаких скоупов в VM, а открывать скоуп в репозитории. Заводить там Job, писать в функции которая возвращает интерактору результат CoroutineScope(IO + Job).launch {}, делать в ней запрос и возвращать результат.
В теории, получится чище. Но очень смущает, что репозиторий ничего не знает о ЖЦ вьюхи.
Т.к, если мне нужно в VM, например, прибить сетевой запрос в ответ на действие пользователя, это просто довольно сделать(viewModelScope.cancel()). А если я буду запускать скоуп из репозитория, то я из UI его как бы не контроллирую вовсе, он там себе работает и всё.
Да и вообще, решил юзер покинуть экран, я из VM раз - и закрыл скоуп, а что будет со скоупом в репозитории мне вообще не ясно что - то. Это выглядит как потенциальный MemoryLeak вообще, т.к юзер покинул экран, а Job в репозитории всё ещё что - то делает.
Вопрос: я в нужном направлении двигаюсь? Норм идея, скоуп в репозитории заводить?
Прикладываю код одного из репозиториев, просто чтобы было. Сам проект фулл переписывается по кд, так что он в огне, ради сохранения психического здоровья не рекомендую смотреть его :D
https://github.com/KirstenLy/LibHelper3/blob/master/app/src/main/java/com/kirsten/libhelper/data/repository/WordRepositoryImpl.kt
Изначальный подход был правильнее, не понимаю, что тебя не устроило
Ну, из своего опыта имеет смысл скоупа вне VM только если нужно там использовать async, например, но для этого есть coroutineScope {}, который также suspend добавляет. На счет VM, то там же есть расширения, 2 скоупа для VM и лайфсайкла. А то, что suspend много в одном место - просто сделать поменьше интерфейсов, ибо там скорее всего разная логика перемешана. А запускать launch внутри репозитория глупо, ибо приложение умрет, а лаунч будет жить, хотя это конечно иногда и специально нужно.
Обсуждают сегодня