1. Introduction

The Kotlin Flow is a key feature of Kotlin coroutines, specifically designed to manage asynchronous data streams. Often, we need to aggregate all the values emitted by a Flow into a List.

In this tutorial, we’ll explore several effective techniques to convert a Flow into a List.

2. Using the toList() Method

The toList() method lets us collect all the values a Flow emits into a List. It handles the emissions and compiles them into a collection for us:

@Test
fun `create list from flow using toList method`() = runTest {
    val flow = flowOf(1, 2, 3)
    val result = flow.toList()

    assertEquals(listOf(1, 2, 3), result)
}

In this snippet, we define a Flow containing a few integers. Then we invoke toList() to transform the Flow into a List. Finally, we check that the final list contains the expected elements.

Furthermore, the toList() method allows us to specify a different mutable list to collect into. For instance, we can use it with a CopyOnWriteArrayList if thread-safety is a concern:

@Test
fun `create list using toList with custom mutable list`() = runTest {
    val flow = flowOf(1, 2, 3)
    val result = CopyOnWriteArrayList<Int>()
    flow.toList(result)

    assertEquals(listOf(1, 2, 3), result)
}

3. Using collect() With a MutableList

The collect() method provides a customizable way to gather values emitted by a Flow into a List. It allows us to define how we want to process each value, making it a flexible option for custom aggregation:

@Test
fun `create list from flow using collect method`() = runTest {
    val flow = flowOf(1, 2, 3)
    val result = mutableListOf<Int>()
    flow.collect { result.add(it) }

    assertEquals(listOf(1, 2, 3), result)
}

Here, the test creates a mutable list named result. Each item is added to this List within the collect block as the Flow emits values. Afterwards, we assert that the resulting list contains all expected values.

4. Using the fold() Method

The fold() method provides an elegant solution for aggregating values into a List. It also allows for intermediate computations or transformations during the collection process. This combination of aggregation and customization makes it versatile and highly useful in many scenarios.

Unlike other collection techniques, fold() needs an accumulator as the initial value and iteratively applies a transformation function to each emission, updating the accumulator as it proceeds:

@Test
fun `create list from flow using fold method`() = runTest {
    val flow = flowOf(1, 2, 3)
    val result = flow.fold(mutableListOf<Int>()) { acc, value ->
        acc.apply { add(value) }
    }
    assertEquals(listOf(1, 2, 3), result)
}

In this example, we initialize an empty MutableList as an accumulator. The fold() method iterates over each emitted value from the Flow and adds it to this accumulator. Finally, we check that the final result matches what we expect.

One important feature is that fold() works even when the Flow is empty, thanks to the initial accumulator value.

5. Conclusion

In this article, we’ve explored several techniques for converting a Kotlin Flow into a List.

First, we examined the toList() method, which provides a simple way to collect emissions without intermediate operations. Following that, we moved on to the collect() function, which allows for customized processing of each emitted value. Finally, we used the fold() operator to iterate through the Flow and put each element into our final list.

Each approach offers distinct advantages, making them well-suited for various use cases in application development.


原始标题:Create a List From Kotlin Flow