3

I am using MutableStateFlow in my project. When we initialise the MutableStateFlow object we need to give default value.

val topics = MutableStateFlow<List<String>>(emptyList())

when I collect this value

[null, "Hello", "world"]

I want to pass this list in adapter . So is there a way we can remove the null object before passing in adapter or Is there any better way ?

viewModel.topics.collect { topicsList ->
    println(topicsList)         // [null, "Hello", "world"]
    adapter.submitList(topicsList)
}
Kotlin Learner
  • 3,995
  • 6
  • 47
  • 127
  • 1
    Seems to me that the null-value comes from the list that you are pushing to the `MutableStateFlow`, not from the `MutableStateFlow` itself. – marstran Jun 09 '22 at 15:09
  • 1
    It's strange that the list contains `null`, in the definition it shouldn't contain `null`: `MutableStateFlow>` – Sergio Jun 09 '22 at 15:26
  • Yes I know that, So what could I do instead of emptylist()? – Kotlin Learner Jun 09 '22 at 15:27
  • 1
    `emptyList` provides an empty list, not `null` object, you need to look to where you set new state to `topics`. – Sergio Jun 09 '22 at 15:28
  • Is this **exactly** the code you use and **exactly** the output you observe? I ask because `println()` in Kotlin usually does not enclose string values in quotation marks, so your output doesn't seem right at all. Maybe you have e.g. string `"null"` in the list, but it's hard to guess if something seems wrong with your examples. – broot Jun 09 '22 at 20:28
  • oh my bad, I am setting null in my list. Sorry guys. – Kotlin Learner Jun 09 '22 at 21:47

6 Answers6

4

If you don't want it to have an enforced initial value, use MutableSharedFlow instead. If you give it replay = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST, and distinctUntilChanged(), it's basically the same thing as a MutableStateFlow without the enforced value. And if onBufferOverflow is not BufferOverflow.SUSPEND, tryEmit will always succeed so you can use tryEmit() instead of value = .

private val _topics = MutableSharedFlow<List<String>>(
    replay = 1,
    onBufferOverflow = BufferOverflow.DROP_OLDEST
)
val topics: Flow<List<String>> = _topics.distinctUntilChanged()

// emitting to the shared flow:
_topics.tryEmit(newValue)
Tenfour04
  • 83,111
  • 11
  • 94
  • 154
2

Since it emits a list of strings you could try to initialise the StateFlow with a null like so

val topics = MutableStateFlow<List<String>?>(null)

And when you collect you can check if the emitted value is null or not

viewModel.topics.collect { topicsList ->
    topicsList?.let { safeTopics ->
        adapter.submitList(safeTopics)
    }
}
Tinashe Makuti
  • 131
  • 1
  • 3
2

If you want to ignore initial value of StateFlow, set initial value null or anything you want. Then you can use filter function on flow.

For example initial value is null

launch {
    val topicsState = MutableStateFlow<List<String?>?>(null)

    topicsState.filterNotNull().map { topics -> topics.filterNotNull() }.onEach { topics ->
        println(topics)
    }.launchIn(this)

    launch {
        delay(1000)
        topicsState.update { listOf(null, "Hello", "world") }
    }
}

Output

[Hello, world]
asissuthar
  • 2,078
  • 1
  • 15
  • 29
1

If we have given a common generic type sealed class.

Common Sealed Class

sealed class Resource<T>(val data: T? = null, val error: String? = null) {
    class Loading<T> : Resource<T>()
    class Success<T>(data: T) : Resource<T>(data = data)
    class Error<T>(error: String) : Resource<T>(error = error)
}

In that case, we can set the initial value like this.

private val _mutableStateFlow: MutableStateFlow<Resource<List<PackageModel>>?> = MutableStateFlow(null)

PackageModel is Model/Pojo class

Hanif Shaikh
  • 500
  • 1
  • 10
0

I think what you need is this:

val sampleList = listOf(null, "Hello", "world")
val topics = MutableStateFlow<List<String>>(sampleList.filer { it != null })
Sam Chen
  • 7,597
  • 2
  • 40
  • 73
0

You can simply ignore the first value by using drop(1) :

viewModel.topics.drop(1).collect { topicsList ->
    ...
}
Mehdi I.
  • 11
  • 3