Vivek Modi
Vivek Modi

Reputation: 7161

How to avoid default value in MutableStateFlow kotlin

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)
}

Upvotes: 6

Views: 9945

Answers (6)

Mehdi I.
Mehdi I.

Reputation: 21

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

viewModel.topics.drop(1).collect { topicsList ->
    ...
}

Upvotes: 1

Mohammad Hanif Shaikh
Mohammad Hanif Shaikh

Reputation: 1481

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

Upvotes: 1

asissuthar
asissuthar

Reputation: 2256

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]

Upvotes: 2

Tinashe Makuti
Tinashe Makuti

Reputation: 161

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)
    }
}

Upvotes: 2

Sam Chen
Sam Chen

Reputation: 8857

I think what you need is this:

val sampleList = listOf(null, "Hello", "world")
val topics = MutableStateFlow<List<String>>(sampleList.filer { it != null })

Upvotes: 0

Tenfour04
Tenfour04

Reputation: 93629

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)

Upvotes: 5

Related Questions