Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!
Когда я начал использовать Room для работы с БД, я задавался вопросом, как же более правильно сформировать подписку на изменения данных в таблице БД, чтобы если при подписке не было данных, то наш репозиторий сразу возвращал пустой список, а не ждал появления данных.
Под подпиской я имею в виду получение текущих данных, а так-же отслеживание изменений в таблице БД и при изменении данных получение их в нашей подписке.
Как вы знаете, для создания подписки возвращающей новые данные при изменении данных в таблице, нужно использовать Flowable из RxJava2.
Примерно так будет выглядеть Dao интерфейс в коде:
@Dao
interface DataDao {
@Query("SELECT * FROM DataTable")
fun getData(): Flowable<List<Data>>
}
Но, теперь если в нашем приложении мы попытаемся получить список Data
из таблицы DataTable, а в таблице нет записей, то наша Flowable подписка будет ждать появления данных в этой таблице, а нам не нужно ждать этого, нам нужно показать пользователю экран с текстом "Нет данных".
dataDao.getData()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe { data ->
//если в таблице нет записей, то наша Flowable подписка будет ждать появления данных в этой таблице
}
Для получения требуемого поведения можно сделать следующе.
Добавляем в Dao функцию получения кол-ва записей в таблице:
@Query("SELECT COUNT(*) FROM DataTable")
fun getDataCount(): Flowable<Int>
Данная функция сразу при вызове вернет значение 0, если в таблице нет данных, а так-же каждый раз при изменении данных в таблице будет иметь новое значение кол-ва записей.
Напишем вот такой код в нашем репозитории для получения необходимого поведения:
class DataRepository(private val dataDao: DataDao) {
fun getData(): Flowable<List<Data>> {
return dataDao.getDataCount().switchMap {
if (it > 0)
dataDao.getData()
else
Flowable.just(emptyList())
}
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
}
}
В итоге мы получаем репозиторий с функцией getData()
который при отсутствии данных в таблице вернет пустой список, а при появлении данных вернет новый список с данными.
Пример использования:
dataRepository.getData()
.subscribe { data ->
//репозиторий вернет либо пустой список, либо список с данными
}
p.s. В данном случае можно еще подумать над тем, что можно у функции getData
в Dao
поменять тип Flowable на Maybe (чтобы внутри нашей подписки не было двух Flowable ожидающих изменения данных в таблице) либо сделать dataDao.getData().take(1)
, но и в приведенном коде репозитория нет ничего криминального:) ведь используется switchMap
.