In my viewmodel i have ``` val tabs = mutableSt...
# compose
z
In my viewmodel i have
Copy code
val tabs = mutableStateListOf(currentLocation)
    var currentTabIndex by mutableIntStateOf(0)

    fun newTab(path: Path = currentLocation) {
        tabs.add(currentTabIndex, path)
        currentTabIndex++
    }
And in another composable I have
Copy code
ScrollableTabRow(
            modifier = Modifier.fillMaxWidth(),
            selectedTabIndex = viewModel.currentTabIndex,
            containerColor = MaterialTheme.colorScheme.surfaceColorAtElevation(3.dp),
            edgePadding = 0.dp
        ) {
            viewModel.tabs.forEachIndexed { index, title ->
The issue that happens is that adding a third tab results in it erroring
Index 2 out of bounds for length 2
If I add a short delay between adding to the tabs list and updating the tab index then it works, but is there a proper way to solve this?
s
Putting both values (tabs and currentTabIndex) into a single state data class and updating this state should become an "atomic change" and solve the issue, I would say.
☝️ 2
z
That should work. I do wanna see what other solutions there are
a
Just wondering here, is the current selected tab considered business logic or ui related logic, should it be inside the viewmodel?
z
business logic I think, it's for browsing files
a
I would think this is ui controller but I might be wrong
s
Where does the exception happen exactly? Also you got
Snapshot.withMutableSnapshot {}
if you really need to atomically update two unrelated states that don't actually fit inside one single object https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:compose/[…]ose/runtime/snapshots/Snapshot.kt;l=431?q=withMutableSnapshot
today i learned 1
z
in my code it happens on the line
selectedTabIndex = viewModel.currentTabIndex
s
Right, what happens inside
ScrollableTabRow
? Accessing the index itself shouldn't throw. Does wrapping the state changes with a
withMutableSnapshot
help here?
z
I'm not sure inside the ScrollableTabRow, I didn't go too deep into debugging. Itll be a while until I can try the withMutableSnapshot
Is this what you mean? It doesn't work
Copy code
fun newTab(path: Path = currentLocation) {
    Snapshot.withMutableSnapshot {
        tabs.add(currentTabIndex, path)
        currentTabIndex++
    }
}
So I should just have a TabRowUiState class, then having a tabRowUiState MutableStateFlow field in my viewmodel?
s
What you need is called a "state holder" in official documentation, I believe. Here is an example of how to create and use it: https://developer.android.com/codelabs/jetpack-compose-advanced-state-side-effects#6
s
If those two states being changed atomically does not change the exception, a state holder wouldn't make a difference either. It would also change the state atomically, but it looks like that by itself isn't working? Somehow? I really am not sure what happens there.
z
if it makes a difference this is on desktop
s
Shouldn't make any difference
z
@Stylianos Gakis I just found something very interesting When I use a PrimaryScrollableTabRow the error doesnt happen. Only with ScrollableTabRow it does
🪄 1
Looking at the implementation, ScrollableTabRow uses subcomposition and PrimaryScrollableTabRow just uses a standard Layout
d
could you make scrollable row fill the whole width of the screen? i use tabrow because i only have 2 tabs (for now) i was thinking of using scrollable in case in the future we want to add more tabs, but scrollableTab is not filling the width of the screen even using fillMaxWidth