Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

What is the proper way to update list state after inserting an item via a repository in Compose?

I have a Room app which displays a list of presets, and the user has the option of adding them by pressing a ‘New Quick Preset’ button:

Code for inserting new item into Room database (in ViewModel):

fun insertQuickPreset(quickPreset: QuickPreset) {
    viewModelScope.launch {
        repository.insertQuickPreset(quickPreset)
    }
}

State:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

data class NewScreenState(
    @StringRes val nameError: Int? = null,
    @StringRes val widthError: Int? = null,
    @StringRes val heightError: Int? = null,
    val name: String = "",
    val width: String = "",
    val height: String = "",
    val quickPresets: List<QuickPreset>
)

Repo:

suspend fun insertQuickPreset(quickPreset: QuickPreset) {
    return withContext(Dispatchers.IO) {
        dao.insert(quickPreset)
    }
}

Composable:

Button(
    modifier = Modifier.align(Alignment.End),
    onClick = {
        viewModel.insertQuickPreset(QuickPreset(55,52))
    }
) {
    Text(
        "New Quick Preset"
    )
}

The issue is, when the user taps ‘New Quick Preset’, the state doesn’t get updated, so for the user to see the results they need to go back and then press the button to enter the screen again.

I took a course in Compose and they never demonstrated how to add items, only how to fetch them. I have the code for adding an item, although I have no idea how I would update the state from here to reflect the added values? I usually utilize the .copy method but this is only for when the database contents are first fetched.

Any help would be appreciated.

>Solution :

Use SnapshotStateList.

val quickPresets: SnapShotStateList

and initializing it this way

val list = mutableStateListOf( your quick presets )

Any updates you do to a SnapshotStateList, such as

  • add new quickPreset
  • remove a quickPreset
  • update a quickPreset via .copy()

is guaranteed to perform a re-composition, assuming its being observed by a composable somewehere

Edit: Assuming you’re using Room database, here is a snippet of my own implementation

Repository

override fun fetchPeople(): Flow<List<People>> =
        peopleDao.getPeople().map { entityList ->
            entityList.map { entity ->
                entity.toModel()
            }
    }

override suspend fun savePerson(PersonModel: PersonModel): Long {
        return peopleDao.insertPerson(PersonModel.toEntity())
}

override suspend fun deletePerson(PersonModel: PersonModel) {
        peopleDao.deletePerson(PersonModel.toEntity())
}

And I’m just observing it via ViewModel

private val _people = mutableStateListOf<Person>()
val people: List<Person> = _people

...
...

viewModelScope.launch {
      repository.fetchPeople()
        .collect {
             _people.addAll(it)
        }
}

For your scrolling issue, you can do something like this,

 val scrollState = rememberLazyListState()
 val coroutineScope = rememberCoroutineScope()
    
 SideEffect {
     coroutineScope.launch {
        scrollState.scrollToItem(index)
     }
 }

Let the composable that contains your list finish what ever it needs to do, and do the scrollToItem after its successful re-composition

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading