У меня вопрос по поводу Flowables
. У меня уже есть несколько решений для этой проблемы, но я хотел бы еще раз проверить, являются ли они наилучшими из возможных решений.
Context
У меня есть Интерактор, который должен закладывать рецепты в БД. Выглядит это так:
/**
* This Interactor marks a recipe as "bookmarked" on the DB. The Interactor actually switches
* the isBookmarked value of the related recipeId. If it was marked as true, it switches its value
* to false. If it was false, then it switches its value to true.
*/
class BookmarkRecipeInteractorImpl(
private val recipesCacheRepository: RecipesCacheRepository
) : BookmarkRecipeInteractor {
override fun execute(recipeId: Int, callback: BookmarkRecipeInteractor.Callback) {
// Fetches the recipe from DB. The getRecipeById(recipeId) function returns a Flowable.
// Internally, within the RecipesCacheRepository, I'm using room.
recipesCacheRepository.getRecipeById(recipeId).flatMap { originalRecipe ->
// Switches the isBookmarked value
val updatedRecipe = originalRecipe.copy(
isBookmarked = !originalRecipe.isBookmarked
)
// Update the DB
recipesCacheRepository.updateRecipe(updatedRecipe)
// Here's the issue, since I'm updating a DB record and the getRecipeById returns
// a Flowable, as soon as I update the DB, the getRecipeById is going to get triggered
// again, and switch the value again, and again, and again...
}
.subscribe(
{
callback.onSuccessfullyBookmarkedRecipe(it.response)
},
{
callback.onErrorFetchingRecipes()
}
)
}
}
Итак, если вы следуете коду, ошибка довольно проста. Я застрял на oop, где постоянно меняю запись рецепта.
Возможные решения
1) Включены две разные функции мой DAO, один с именем getRecipeByIdFlowable(id)
, который возвращает Flowable, а другой с именем getRecipeByIdSingle(id)
, который возвращает rx.Single. Таким образом, я могу выставить getRecipeByIdSingle(id)
через репозиторий и использовать его вместо функции, которая возвращает Flowable. Таким образом я обрезал l oop.
Pro: Это работает.
Con: Мне не нравится, когда такие функции есть в моем DAO.
2) Сохраните Disposable
для свойства lateinit
и утилизируйте его, как только подписчик вызовет onNext()
.
Pro: Это работает.
Con: Мне не нравится делать что-то подобное, я чувствую себя хакером.
3) Использование ...getRecipeById(recipeId).take(1).flatMap...
, поэтому он обрабатывает только первый испущенный объект.
Pro: Работает, выглядит аккуратно.
Con: Я не уверен, есть ли лучший способ сделать это.
Вопрос
В идеале я хотел бы вызвать какую-то функцию, которая просто позволяет мне отключить поведение Flowable
и не дать ему испускать больше элементов при изменении БД. Пока что решение, которое мне нравится больше всего, это # 3, но я не совсем уверен, что это правильный способ сделать это.
Спасибо!
Редактировать 1
Я просто добавляю немного больше информации о сценарии использования здесь. Мне нужен Interactor, который при recipeId изменяет значение isBookmarked на БД на его противоположное.
Записи БД выглядят следующим образом:
data class DbRecipeDto(
@PrimaryKey
val id: Int,
val name: String,
val ingredients: List<String>,
val isBookmarked: Boolean = false
)
Я знаю, что, может быть, есть и другие способы, которыми я мог бы решить эту проблему по-другому. Возможно, я мог бы передать аргумент recipeId arg и аргумент закладки (Boolean) и просто выполнить запрос на обновление.
Но в этом случае использования он полностью составлен, просто пример ; То, что я пытаюсь выяснить , как запретить Flowable испускать больше элементов, если что-то изменится в DB .