I have a god view model for every thing I know this is wrong but I am just experimenting with Flow
I have these two State flow variables in view model
private val _currentRestroMenu = MutableStateFlow<State<Menu>>(State.loading())
private val _userCart = MutableStateFlow(CustomerCart())
val currentRestroMenu: StateFlow<State<Menu>> = _currentRestroMenu
val userCart: StateFlow<CustomerCart> = _userCart
Below functions get data from server and update above state flow
private fun getRestroMenuFromCloudAndUpdateData(restroId: String) = viewModelScope.launch {
fireStoreRepository.getRestroMenu(restroId).collect { state ->
when (state) {
is State.Success -> {
_currentRestroMenu.value = State.success(state.data)
dataHolderMenuOnSearch = state.data
if (!viewedRestroMenu.contains(state.data)) {
viewedRestroMenu.add(state.data)
}
}
is State.Failed -> {
_currentRestroMenu.value = State.failed(state.message)
}
is State.Loading -> {
_currentRestroMenu.value = State.loading()
}
}
}
}
private fun getCart() = viewModelScope.launch(Dispatchers.IO) {
if (currentCart.cartEmpty) {
fireStoreRepository.getUserCartInfoFromCloud(dataStoreRepository.readFileDataStoreValue.first().savedUserId)
.collect { cartState ->
when (cartState) {
is State.Success -> {
_userCart.update {
it.copy(
cartId = cartState.data.cartId,
cartEmpty = cartState.data.cartEmpty,
cartItem = cartState.data.getCartItem(),
restroId = cartState.data.restroId,
cartTotalAmount = cartState.data.cartTotalAmount,
cartAddressId = cartState.data.cartAddressId,
cartDeliveryTime = cartState.data.cartDeliveryTime,
cartCookingInstructions = cartState.data.cartCookingInstructions,
cartAppliedOfferId = cartState.data.cartAppliedOfferId,
deliveryPartnerTipAmount = cartState.data.deliveryPartnerTipAmount,
cartDeliveryCharge = cartState.data.cartDeliveryCharge,
cartTax = cartState.data.cartTax,
deliveryInstructionId = cartState.data.deliveryInstructionId,
foodHandlingCharge = cartState.data.foodHandlingCharge,
cartNumberOfItems = cartState.data.cartNumberOfItems,
cartRestroName = cartState.data.cartRestroName
)
}
currentCart = cartState.data
}
is State.Failed -> {
if (cartState.message == "Result null") {
Log.d(
ContentValues.TAG,
"getCartFromCloud: No cart details found in cloud creating new cart"
)
_userCart.update {
it.copy(
cartId = dataStoreRepository.readFileDataStoreValue.first().savedUserId,
cartEmpty = true
)
}
currentCart = CustomerCart(
cartId = dataStoreRepository.readFileDataStoreValue.first().savedUserId,
cartEmpty = true
)
}
}
is State.Loading -> {
Log.d(ContentValues.TAG, "getCartFromCloud: Loading")
}
}
}
} else {
_userCart.value = currentCart
Log.d(ContentValues.TAG, "getCart: $currentCart ")
}
}
I am collecting these state flow from different fragments every thing works fine except one fragment
here is the code
in on create method
viewLifecycleOwner.lifecycleScope.launch {
viewLifecycleOwner.lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
godCustomerViewModel.currentRestroMenu.collectLatest { menuState ->
Log.d(TAG, "currentRestroMenu ::: mENUSELECT FIRED: ")
when (menuState) {
is State.Success -> {
restroMenu = menuState.data
binding.recyclerView2.hideShimmer()
getCartDetails(restroMenu)
}
is State.Failed -> {
Log.d(TAG, "currentRestroMenu: ")
}
is State.Loading -> {
binding.recyclerView2.showShimmer()
}
}
}
}
}
private fun getCartDetails(restroMenu: Menu) = viewLifecycleOwner.lifecycleScope.launch {
viewLifecycleOwner.lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
godCustomerViewModel.userCart.collectLatest {
if (it.restroId == restroMenu.restroId) {
categoryAdapterRestroDetails.setData(
restroMenu.menuCategories,
it.getCartItem()
)
} else {
categoryAdapterRestroDetails.setData(
restroMenu.menuCategories,
ArrayList()
)
}
}
}
}
I am passing the two collected values to adapter (retro menu and item in cart )
when the fragment is loaded for the first time everything works fine
I have add dish to cart function which updates the value of user cart
fun addDishToCart(dish: Dish) = viewModelScope.launch {
Log.d(ContentValues.TAG, "addDishToCart: view model invoked")
if (currentCart.checkIfCartBelongsToThisRestro(dish.dishRestroId)) {
currentCart.addDishToCart(dish).collect {
Log.d(ContentValues.TAG, "addDishToCartcollect: $currentCart")
_userCart.update {
it.copy(
cartEmpty = currentCart.cartEmpty,
cartItem = currentCart.getCartItem(),
restroId = currentCart.restroId,
cartTotalAmount = currentCart.cartTotalAmount,
cartNumberOfItems = currentCart.cartNumberOfItems,
)
}
}
} else {
// restro Conflict
Log.d(ContentValues.TAG, "addDishToCart: $currentCart")
_restroConflict.value = CartConflict(true, currentCart.cartRestroName, dish)
}
Log.d(ContentValues.TAG, "addDishToCart current cart: ${currentCart.getCartItem()}")
Log.d(ContentValues.TAG, "addDishToCart: user Cart : ${_userCart.value.getCartItem()} ")
}
Which also work fine initially
I also have a button to filter menu to veg non veg
fun filterMenuForVeg(value: Boolean, showAll: Boolean) = viewModelScope.launch {
if (!showAll) {
Log.d(ContentValues.TAG, "filterMenuForVeg: Entered veg :$value")
var filteredMenu = Menu()
filteredMenu.restroId = dataHolderMenuOnSearch.restroId
for (menuCategory in dataHolderMenuOnSearch.menuCategories) {
Log.d(ContentValues.TAG, "filterMenuForVeg: $dataHolderMenuOnSearch ")
for (dish in menuCategory.dishes) {
if (dish.dishVeg == value) {
Log.d(ContentValues.TAG, "found dish with veg $value: ")
var categoryAlreadySaved = false
filteredMenu.menuCategories.filter {
categoryAlreadySaved = it.categoryId == menuCategory.categoryId
true
}
if (!categoryAlreadySaved) {
Log.d(ContentValues.TAG, "menu category not found in filtered list ")
val menuCategoryToAdd = MenuCategories()
menuCategoryToAdd.menuCategoryName = menuCategory.menuCategoryName
menuCategoryToAdd.categoryId = menuCategory.categoryId
menuCategoryToAdd.restroId = menuCategory.restroId
menuCategoryToAdd.dishes.add(dish)
filteredMenu.menuCategories.add(menuCategoryToAdd)
} else {
Log.d(ContentValues.TAG, "menu category found in filtered list ")
filteredMenu.menuCategories.find {
if (it.categoryId == menuCategory.categoryId) {
it.restroId = menuCategory.restroId
it.dishes.add(dish)
}
true
}
}
}
}
}
Log.d(ContentValues.TAG, "filterMenuForVeg : $filteredMenu ")
_currentRestroMenu.value = State.success(filteredMenu)
} else {
// set to all data
_currentRestroMenu.value = State.success(dataHolderMenuOnSearch)
}
When I filter dish for veg or non veg then add dish to cart (Which only changes userCart State flow) the place where I am collecting these state flow get fired twice so set data to adapter is getting called twice
What Iam doing wrong