Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

589
Views
How to manually update a kotlin flow

I'm trying to update the source of a Flow in Kotlin and I'm not sure if this is the right approach and if it's possible with Flow at all.

I have a database containing posts for a user and this returns me a Flow<List<Post>>. Now when I select another user I want the flow of the database to return me the posts of the newly selected user:


lateinit var userPosts: Flow<List<Post>>
   private set

fun getPostsForUser(user: User) {
   userPosts = database.getAllPostsForUser(user)
}

But the flow never gets updated with the data of the new selected user. Is Flow still the right choice in this case and if yes, how can I update the flow with the new posts?

I know how to do it manually with fetching data from the database and emitting it using LiveData, but I would like to avoid handling the update of posts everytime the user posts something new or a post is deleted.

over 4 years ago · Santiago Trujillo
2 answers
Answer question

0

I think maybe you're collecting one flow, and then setting a user, which changes the flow in the property, but not any existing previous flow that's already being collected. I'm not sure how else to explain what's happening.

It may be error-prone to have a public Flow property that is reliant on some other function that takes a parameter. You could return a Flow directly from the function so there is no ambiguity about the behavior. The fragment requests a Flow for a specific User and immediately gets it.

distinctUntilChanged() will prevent it from emitting an unchanged list that results from other changes in the repo.

fun getPostsForUser(user: User) Flow<List<Post>> =
    database.getAllPostsForUser(user).distinctUntilChanged()

If you do want to use your pattern, I think it you could do it like this. This allows there to only ever be one Flow so it's safe to start collecting it early. Changing the user will change which values it's publishing. Although this is more complicated than above, it has the advantage of not requiring a data refresh on screen rotations and other config changes.

private val mutableUserPosts = MutableStateFlow<List<Post>>(emptyList())
val userPosts: Flow<List<Post>> = mutableUserPosts

private var userPostsJob: Job? = null
var user: User? = null
    set(value) {
        field = value
        userPostsJob?.cancel()
        value ?: return
        userPostsJob = database.getAllPostsForUser(value)
            .onEach { mutableUserPosts.emit(it) }
            .launchIn(viewModelScope)
    }

Or as Joffrey suggests, it's simpler with a User Flow if you don't mind using the unstable API function flatMapLatest. The user property here could be dropped if you don't mind exposing a public mutable flow where the value should be set externally. Or if you use this pattern repeatedly, you could make operator extension functions for StateFlow/MutableStateFlow to use it as a property delegate.

private val userFlow = MutableStateFlow<User?>(null)
var user: User?
    get() = userFlow.value
    set(value) {
        userFlow.value = value
    }

val userPosts: Flow<List<Post>> = userFlow.flatMapLatest { user ->
    if (user == null) emptyFlow() else database.getAllPostsForUser(user)
}
over 4 years ago · Santiago Trujillo Report

0

This might be helpful for someone...

When you are collecting a flow downstream and in some situations, you need an updated flow or a completely different flow than before, Use flatmapLatest() function.

Example:

There is a flow of search results in an app. When a user enters a search text flow automatically should update with the latest data according to searched chars.

Place the query text in a StateFlow as,

private var _userSearchText = MutableStateFlow("")
val userSearchText = _userSearchText.asStateFlow()

as the user enters text just update the Stateflow as,

fun setUserNameSearchText(data: String) {
   _userSearchText.value = data
}

and your flow collecting like,

val response = userSearchText.flatMapLatest {
    searchRepository.getResults(it)
        .cachedIn(viewModelScope)
}

Stateflow will trigger the API calls automatically. It will notify all the observers on them.

PS: Open to improving...

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!