I have fun with viewModelScope.launch written in v...
# compose
n
I have fun with viewModelScope.launch written in viewModel for removing an item from cart, there's a condition in compose item card which disables the remove icon when last part is remaining in the list, but when I click on the remove button on 2 of the last cards, both the items gets removed. I already tried mutex, checking with a mutableStateOf boolean value, adding @Synchronized on the fun, but nothing works ? how should I handle this race condition?
s
Could you share your ViewModel’s and Compose code?
n
there isn't much there, just simple fun in viewModel, and normal lazycolumn
Copy code
LazyColumn(
   ...
) {
    items(
        items = selectedItems,
        key = { item -> item.id },
        contentType = { _ -> "SelectedItem" }
    ) { item ->
        val condition = !(item.inCertainCategory && item.part_desc?.contains("xyz", ignoreCase = true) == false) &&
                selectedItems.count {
                    it.inCertainCategory && it.part_desc?.contains("xyz", ignoreCase = true) == true
                } > 1
        SelectedPartItem(
            modifier = Modifier.animateItem(),
            item = item,
            isEditEnabled = condition,
            onAdd = { onAddMinusItem(true, item) },
            onMinus = { onAddMinusItem(false, item) },
            onRemove = { onRemoveItem(item) }
        )
    }
}
Copy code
fun removeItem(...) {
    viewModelScope.launch {
        ...
    }
}
s
which disables the remove icon when last part is remaining in the list
What “when last part is remaining in the list” means?
when I click on the remove button on 2 of the last cards, both the items gets removed.
That sounds correct, if remove button is available when you click on it the item gets removed 🤔
Without more context I suggest • Check how you update
selectedItems
• Check the
condition
try to break it down and make more readable
n
Yes, the button is disabled, when the second last item is removed, so the condition is working correct, just when I click those items simultenously this condition doesn't work
s
But how can you click it if the button is disabled?
n
just with 2 fingers, at the same time
s
You are clicking the same item with 2 fingers?
n
for e.g there are last 2 items remaining in the list, I click on both of them simultaneously, both of them gets removed
s
So when there are 2 last items in the list, they are both clickable, but as soon as you remove one there should be only one item left that is not clickable correct?
n
yep
s
Ok, could you show your
Copy code
fun removeItem(...) {
    viewModelScope.launch {
        ...
    }
}
And how you apply Mutex in particular
n
Copy code
private val estimateMutex = Mutex()

fun removeItem(...) {
    if (quantity < 0) return

    viewModelScope.launch {
        estimateMutex.withLock {

         }
     }
}
s
Move quantity check under
withLock
because now it passes for both clicks
If I understand correctly what
quantity
means 😅
Copy code
fun removeItem(...) {
    viewModelScope.launch {
        estimateMutex.withLock {
               if (quantity < 0) return
               // do something
               quantity = x
         }
     }
}
And of course be careful with changing (and reading)
quantity
outside of Mutex
n
see, in the remove item the quatity is being sent as 0 as default, so that the fun just return & ends it's execution, it unrelated to the logic or removing the item, just a check for minus qtys
s
Then put a different check in there like
Copy code
fun removeItem(...) {
    viewModelScope.launch {
        estimateMutex.withLock {
             // Check if the item can be removed
         }
     }
}
Or for an easy fix you can probably just do
Copy code
if (mutex.isLocked) return
j
I don’t think the quantity check is correct. Its checking when the quantity is less than zero which should never happen. Should it be
if (quantity <= 0) return
or
if (quantity < 1) return
I believe the
removeItem(…)
always executes and never returns early.
s
it unrelated to the logic or removing the item, just a check for minus qtys
It’s unrelated I think the problem here is that no logic guards the execution of removal 2 clicks schedule 2 coroutines to execute, and wrapping them with Mutex is not enough — doing so will only guarantee their execution in sequence, one after another, no racing conditions — however still both will be executed Since UI can send remove requests “uncontrollably” (using two, three, fours… fingers) there should be something that will check the validity of every new request
n
Yes, tried adding a validation in viewModel fun itself, and now I don't know why, but the condition is working, Thanks
😃 1