Почему мне нужно переопределять метод сбора, чтобы использовать Flow in the Room DAO с настраиваемым объектом? ⇐ Android
-
Гость
Почему мне нужно переопределять метод сбора, чтобы использовать Flow in the Room DAO с настраиваемым объектом?
У меня есть собственный объект под названием SyncStatus, и я хочу получить данные из таблицы в Room и сопоставить их с этим объектом. Я также хочу использовать Flow для обновления пользовательского интерфейса при каждом изменении данных в базе данных.
Код работает так, как ожидалось, но мне пришлось создать этот метод в SyncStatus:
//Зачем мне объявлять этот метод здесь? переопределить приостановку развлечения Collect(collector: FlowCollector) { коллектор.emit(это) } Поскольку у меня нет большого опыта работы с Kotlin или сопрограммами, я хотел бы знать, почему SyncStatus должен иметь этот метод и является ли это правильным способом сделать то, что я хочу.
>
Ниже я объясню, как я организовал код: я использую шаблон MVVM и Hilt в качестве внедрения зависимостей.
Статус синхронизации
class SyncStatus : Flow { вар tableName = "" вар версияDB = 1 вар LastUpdate = "" @Игнорировать вар LastYearCleaned = 0 @Игнорировать вар isWorkScheduled = правда @Игнорировать источник var: Source = Source.LOCAL конструктор() @Игнорировать конструктор (lastUpdate: String, LastYearCleaned: Int) { this.lastUpdate = последнее обновление this.lastYearCleaned = LastYearCleaned } fun getAll(isNightMode: Boolean): String { ColorUtils.isNightMode = isNightMode val title = Utils.formatSubTitle(Utils.toRedFont("Информация о синхронизации")) this.tableName = Utils.formatDate(tableName, "ггггММдд", "гггг-ММ-дд") val LastYear = if (lastYearCleaned == 0) "" else String.format( "Лос-даты прошлого %s пламенного света.", Utils.toRedFont(lastYearCleaned.toString()) ) вернуть String.format( "%s" + "%s" + "Последнее сообщение в календаре: " + "%s (*)" + "%sÚltima синхронизация: %s" + "%s" + "%s" + "%s%s..............%s%s(*) Календарь периодически синхронизируется при подключении к Интернету.", заголовок, Константы.BRS, Utils.toRedFont(имя_таблицы), Константы.BRS, Константы.BR, Utils.toRedFont(lastUpdate), Константы.BRS,lastYear, Константы.BRS, Константы.BR, Константы.BR ) } весело getNotWorkerMessage(isNightMode: Boolean): Spanned { ColorUtils.isNightMode = isNightMode вернуть Utils.fromHtml(String.format( "%s
Синхронизация не активирована.", Utils.toRedFont("АВИСО") )) } весело getWorkerMessage(): Spanned { return Utils.fromHtml("
Автоматическая синхронизация активирована.
") } переопределить приостановку развлечения Collect(collector: FlowCollector) { коллектор.emit(это) } } ДАО @Transaction @Запрос( «ВЫБЕРИТЕ ss.lastUpdate,ss.versionDB», + "(SELECT max(todayDate) FROM Today) tableName " + "ИЗ sync_status сс;" ) весело LastSyncStatus(): Flow Модель просмотра @HiltViewModel класс SyncViewModel @Inject конструктор( частный вал getSyncUseCase: GetSyncUseCase, частный val coroutineDispatcherProvider: CoroutineDispatcherProvider ) : ViewModel() { частный val _uiState = MutableStateFlow(SyncUiState.Empty) val uiState: StateFlow = _uiState fun launchSync(syncRequest: SyncRequest) { _uiState.value = SyncUiState.Loading viewModelScope.launch(coroutineDispatcherProvider.IO()) { пытаться { val result = getSyncUseCase.execute(syncRequest) _uiState.value = SyncUiState.Loaded(SyncItemUiState(результат)) } catch (ошибка: исключение) { _uiState.value = SyncUiState.Error(error.message.toString()) } } } запечатанный класс SyncUiState { объект пустой: SyncUiState() Загрузка объекта: SyncUiState() класс Loaded(val itemState: SyncItemUiState): SyncUiState() Ошибка класса (сообщение val: String): SyncUiState() } } Фрагмент private приостановить веселье onLoaded(syncItemUiState: SyncItemUiState) { syncItemUiState.run { getViewBinding().progressBar.visibility = View.GONE val syncResponse = syncItemUiState.syncResponse syncResponse.syncStatus.collect { это -> println(it.lastUpdate) println(it.tableName) mTextVieww.text = Utils.fromHtml(it.getAll(isNightMode())) если (!it.isWorkScheduled) { getViewBinding().include.tvBottom.text = it.getNotWorkerMessage(isNightMode()) } еще { getViewBinding().include.tvBottom.text = it.getWorkerMessage() } } } } Синхронный ответ класс SyncResponse( _syncStatus: Flow, _allToday: Список = пустойСписок() ) { var syncStatus: Flow = _syncStatus var allToday: List = _allToday } Пример использования класс GetSyncUseCase @Inject конструктор( частный вал mRepository: SyncRepository ) { приостановить веселье выполнить (syncRequest: SyncRequest): SyncResponse { вернуть mRepository.getSync(syncRequest) } } Репозиторий интерфейс SyncRepository { приостановить веселье getSync(syncRequest: SyncRequest): SyncResponse } RepositoryImpl переопределить приостановку развлечения getSync(syncRequest: SyncRequest): SyncResponse { вернуть syncFactory.create(Source.LOCAL).getSync(syncRequest) } Завод конструктор класса SyncFactory @Inject( частный вал networkSyncEntityData: NetworkSyncEntityData, частный вал localSyncEntityData: LocalSyncEntityData, частный вал firebaseSyncEntityData: FirebaseSyncEntityData ) { весело создать (источник: Источник): SyncEntityData { вернуться, когда (источник) { Source.NETWORK → networkSyncEntityData Source.LOCAL -> localSyncEntityData еще -> firebaseSyncEntityData } } } LocalSyncEntityData переопределить приостановку развлечения getSync(syncRequest: SyncRequest): SyncResponse { val se = TodayDao.lastSyncStatus() если (syncRequest.yearToClean != 0) { val rowsDeleted = TodayDao.deleteLastYear(syncRequest.yearToClean) если (rowsDeleted > 0) { //se.lastYearCleaned = syncRequest.yearToClean - 1 } } se.source = Source.LOCAL вернуть SyncResponse(se) }
У меня есть собственный объект под названием SyncStatus, и я хочу получить данные из таблицы в Room и сопоставить их с этим объектом. Я также хочу использовать Flow для обновления пользовательского интерфейса при каждом изменении данных в базе данных.
Код работает так, как ожидалось, но мне пришлось создать этот метод в SyncStatus:
//Зачем мне объявлять этот метод здесь? переопределить приостановку развлечения Collect(collector: FlowCollector) { коллектор.emit(это) } Поскольку у меня нет большого опыта работы с Kotlin или сопрограммами, я хотел бы знать, почему SyncStatus должен иметь этот метод и является ли это правильным способом сделать то, что я хочу.
>
Ниже я объясню, как я организовал код: я использую шаблон MVVM и Hilt в качестве внедрения зависимостей.
Статус синхронизации
class SyncStatus : Flow { вар tableName = "" вар версияDB = 1 вар LastUpdate = "" @Игнорировать вар LastYearCleaned = 0 @Игнорировать вар isWorkScheduled = правда @Игнорировать источник var: Source = Source.LOCAL конструктор() @Игнорировать конструктор (lastUpdate: String, LastYearCleaned: Int) { this.lastUpdate = последнее обновление this.lastYearCleaned = LastYearCleaned } fun getAll(isNightMode: Boolean): String { ColorUtils.isNightMode = isNightMode val title = Utils.formatSubTitle(Utils.toRedFont("Информация о синхронизации")) this.tableName = Utils.formatDate(tableName, "ггггММдд", "гггг-ММ-дд") val LastYear = if (lastYearCleaned == 0) "" else String.format( "Лос-даты прошлого %s пламенного света.", Utils.toRedFont(lastYearCleaned.toString()) ) вернуть String.format( "%s" + "%s" + "Последнее сообщение в календаре: " + "%s (*)" + "%sÚltima синхронизация: %s" + "%s" + "%s" + "%s%s..............%s%s(*) Календарь периодически синхронизируется при подключении к Интернету.", заголовок, Константы.BRS, Utils.toRedFont(имя_таблицы), Константы.BRS, Константы.BR, Utils.toRedFont(lastUpdate), Константы.BRS,lastYear, Константы.BRS, Константы.BR, Константы.BR ) } весело getNotWorkerMessage(isNightMode: Boolean): Spanned { ColorUtils.isNightMode = isNightMode вернуть Utils.fromHtml(String.format( "%s
Синхронизация не активирована.", Utils.toRedFont("АВИСО") )) } весело getWorkerMessage(): Spanned { return Utils.fromHtml("
Автоматическая синхронизация активирована.
") } переопределить приостановку развлечения Collect(collector: FlowCollector) { коллектор.emit(это) } } ДАО @Transaction @Запрос( «ВЫБЕРИТЕ ss.lastUpdate,ss.versionDB», + "(SELECT max(todayDate) FROM Today) tableName " + "ИЗ sync_status сс;" ) весело LastSyncStatus(): Flow Модель просмотра @HiltViewModel класс SyncViewModel @Inject конструктор( частный вал getSyncUseCase: GetSyncUseCase, частный val coroutineDispatcherProvider: CoroutineDispatcherProvider ) : ViewModel() { частный val _uiState = MutableStateFlow(SyncUiState.Empty) val uiState: StateFlow = _uiState fun launchSync(syncRequest: SyncRequest) { _uiState.value = SyncUiState.Loading viewModelScope.launch(coroutineDispatcherProvider.IO()) { пытаться { val result = getSyncUseCase.execute(syncRequest) _uiState.value = SyncUiState.Loaded(SyncItemUiState(результат)) } catch (ошибка: исключение) { _uiState.value = SyncUiState.Error(error.message.toString()) } } } запечатанный класс SyncUiState { объект пустой: SyncUiState() Загрузка объекта: SyncUiState() класс Loaded(val itemState: SyncItemUiState): SyncUiState() Ошибка класса (сообщение val: String): SyncUiState() } } Фрагмент private приостановить веселье onLoaded(syncItemUiState: SyncItemUiState) { syncItemUiState.run { getViewBinding().progressBar.visibility = View.GONE val syncResponse = syncItemUiState.syncResponse syncResponse.syncStatus.collect { это -> println(it.lastUpdate) println(it.tableName) mTextVieww.text = Utils.fromHtml(it.getAll(isNightMode())) если (!it.isWorkScheduled) { getViewBinding().include.tvBottom.text = it.getNotWorkerMessage(isNightMode()) } еще { getViewBinding().include.tvBottom.text = it.getWorkerMessage() } } } } Синхронный ответ класс SyncResponse( _syncStatus: Flow, _allToday: Список = пустойСписок() ) { var syncStatus: Flow = _syncStatus var allToday: List = _allToday } Пример использования класс GetSyncUseCase @Inject конструктор( частный вал mRepository: SyncRepository ) { приостановить веселье выполнить (syncRequest: SyncRequest): SyncResponse { вернуть mRepository.getSync(syncRequest) } } Репозиторий интерфейс SyncRepository { приостановить веселье getSync(syncRequest: SyncRequest): SyncResponse } RepositoryImpl переопределить приостановку развлечения getSync(syncRequest: SyncRequest): SyncResponse { вернуть syncFactory.create(Source.LOCAL).getSync(syncRequest) } Завод конструктор класса SyncFactory @Inject( частный вал networkSyncEntityData: NetworkSyncEntityData, частный вал localSyncEntityData: LocalSyncEntityData, частный вал firebaseSyncEntityData: FirebaseSyncEntityData ) { весело создать (источник: Источник): SyncEntityData { вернуться, когда (источник) { Source.NETWORK → networkSyncEntityData Source.LOCAL -> localSyncEntityData еще -> firebaseSyncEntityData } } } LocalSyncEntityData переопределить приостановку развлечения getSync(syncRequest: SyncRequest): SyncResponse { val se = TodayDao.lastSyncStatus() если (syncRequest.yearToClean != 0) { val rowsDeleted = TodayDao.deleteLastYear(syncRequest.yearToClean) если (rowsDeleted > 0) { //se.lastYearCleaned = syncRequest.yearToClean - 1 } } se.source = Source.LOCAL вернуть SyncResponse(se) }
Мобильная версия