EN VI

Android - Display dynamic list of items which are not saved in local room database?

2024-03-11 20:30:05
How to Android - Display dynamic list of items which are not saved in local room database

I have two StateFlows of lists in ViewModel (local and remote), which are combined into single uiState, which is used in Compose user interface.

User is picking values from remote source which are saved into local room database. And I want to filter values from remote data source to display only these values that are not already saved into local DB.

Below is my current solution, but it is not working as I want to.

When I save entity into local DB, it is instantly displayed in list of local values but it does not disappear from remote list. I think it is because there is no change in remoteFlow so it will not emit new value and map is not used.

When user do action to refresh API, remoteFlow will emit new value, map will filter results and result is ok then. But I need this "second impulse" to make it work.

Local data source created from room database:

private val localFlow: StateFlow<List<LocalEntity>> =
        repository.local.getLocalEntity().stateIn(
            scope = viewModelScope,
            started = SharingStarted.WhileSubscribed(5_000L),
            initialValue = listOf()
        )

Remote data source is filled on users requests (clicks) manually using retrofit.

private val remoteFlow: MutableStateFlow<List<remoteEntity>> =
        MutableStateFlow(listOf())

Both flows of lists are combined into uiState. I tried to use map to achive desired filtering.

val uiState = combine(
        remoteFlow.map { remoteList ->
            remoteList.filter { remote -> localFlow.value.firstOrNull { remote.id == it.id} == null }
        }
            .stateIn(
                viewModelScope,
                started = SharingStarted.WhileSubscribed(5_000L),
                initialValue = listOf()
            ),
        localFlow
    ) { remote, local->
        JobListUiState(remote, local)
    }.stateIn(
        scope = viewModelScope,
        started = SharingStarted.WhileSubscribed(5_000L),
        initialValue = JobListUiState()
    )

What is corect approach to achieve this? Is is possible to detect changes in remote list where new item is added to local list?

Solution:

You could perform the filtering inside the combine's transform which will be called on updates to the local data source.

val uiState = combine(
    remoteFlow,
    localFlow,
) { remote, local ->
    val localIds = mutableSetOf<Int>()
    local.mapTo(localIds) { it.id }
    val remoteFiltered = remote.filter { !localIds.contains(it.id) }
    JobListUiState(remoteFiltered, local)
}.stateIn(
//----
Answer

Login


Forgot Your Password?

Create Account


Lost your password? Please enter your email address. You will receive a link to create a new password.

Reset Password

Back to login