и выводит его в RecyclerView. При наличии сети данные жсона при помощи Room сохраняются в базу данных, чтобы потом при отсутствии сети показаться пользователю.
В onCreateView() вызываем viewModel.getPokemons(). Там try-catch блок, в нём делаем запрос к серверу. Если сеть есть, выполняется try, парсит жсон и сохраняет данные в БД.
При отсутствии сети выполняется catch блок, где я и столкнулся с проблемой, потому что список оказывается равным null.
В строке 46 я беру список из базы данных и присваиваю его pokemonList.
Я правильно понимаю, что список равен null в момент использования его адаптером из-за метода postValue, потому что postValue срабатывает уже после присваивания адаптера, до тех пор он null?
И обычный setValue я не могу использовать, потому что дело происходит в корутине. А без корутины не обойтись, потому что чтение из БД должно происходить не в главном потоке. Вот такой порочный круг, как из него выйти?
работая с лайвдатой в саспенд функциях нужно использовать postValue(), а не просто value. Пост гарантирует нормальную работу в разных потоках строки 41 и 43
Да, но при отсутствии сети эти строки вообще не выполняются и код уходит в catch блок, где я как раз использую postValue и это не работает. При наличии сети все значения выводятся корректни и ретрофит берет данные с сервера. Проблема именно при отсутствии сети
1. Может данные в репозитории на самом деле null? В таком случае сделайте проверку, если они null тогда передайте просто пустой список, аля emptyArrayList(). Проверить это можно с помощью дебагера я думаю... 2. Почему используете runBlocking вместо lifecycleScope.launch { }
getPokemonsFromDatabase() покажите метод
Смотря что ты кидаешь в PokemonApi.Error
Первый скрин. На втором DAO.
не знаю, на сколько это правильно, но я обычно в репозитории делаю запрос на Dispatchers.IO, а во вью модели уже работаю в viewModelScope на главном потоке - при вызове метода из репозитория у тебя по идее сам запрос на ИО поток уйдет
При отсутствии сети в бд уже что-то есть?
Ты сетишь пустой список из пустой бд
Данные в репозитории не null, и если например запустить такую функцию, то выводится List со всеми данными. Просто с этой postValue данные списку присваиваются уже после использования его адаптером. По этой причине я в отчаянии использовал runBlocking - думал, что пусть все потоки заблокируются, значение списку присвоится, а потом уже адаптер его использует. Не помогло.
у вас метод в ДАО не саспенд
попробуйте рефактор кода по примеру того как предложил Сергей. Это избавит вас от необходимости использовать postvalue
хз, попробуй сделать так - в репозитории возвращай withContext(Dispatchers.IO) {// запрос к бд тут}, и во вью модели используй value
ну и в репозитории, соответственно
Обсуждают сегодня