1 /*
2 * Copyright (C) 2024 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 @file:OptIn(ExperimentalTypeInference::class)
18
19 package com.android.systemui.utils.coroutines.flow
20
21 import kotlin.experimental.ExperimentalTypeInference
22 import kotlinx.coroutines.flow.Flow
23 import kotlinx.coroutines.flow.FlowCollector
24 import kotlinx.coroutines.flow.conflate
25 import kotlinx.coroutines.flow.flatMapLatest
26 import kotlinx.coroutines.flow.mapLatest
27 import kotlinx.coroutines.flow.transformLatest
28
29 /**
30 * Returns a flow that emits elements from the original flow transformed by [transform] function.
31 * When the original flow emits a new value, computation of the [transform] block for previous value
32 * is cancelled.
33 *
34 * For example, the following flow:
35 * ```
36 * flow {
37 * emit("a")
38 * delay(100)
39 * emit("b")
40 * }.mapLatest { value ->
41 * println("Started computing $value")
42 * delay(200)
43 * "Computed $value"
44 * }
45 * ```
46 *
47 * will print "Started computing a" and "Started computing b", but the resulting flow will contain
48 * only "Computed b" value.
49 *
50 * This operator is [conflated][conflate] by default, and as such should be preferred over usage of
51 * [mapLatest], due to the latter's default configuration of using an internal buffer, negatively
52 * impacting system health.
53 *
54 * @see mapLatest
55 */
mapLatestConflatednull56 fun <T, R> Flow<T>.mapLatestConflated(@BuilderInference transform: suspend (T) -> R): Flow<R> =
57 mapLatest(transform).conflate()
58
59 /**
60 * Returns a flow that switches to a new flow produced by [transform] function every time the
61 * original flow emits a value. When the original flow emits a new value, the previous flow produced
62 * by `transform` block is cancelled.
63 *
64 * For example, the following flow:
65 * ```
66 * flow {
67 * emit("a")
68 * delay(100)
69 * emit("b")
70 * }.flatMapLatest { value ->
71 * flow {
72 * emit(value)
73 * delay(200)
74 * emit(value + "_last")
75 * }
76 * }
77 * ```
78 *
79 * produces `a b b_last`
80 *
81 * This operator is [conflated][conflate] by default, and as such should be preferred over usage of
82 * [flatMapLatest], due to the latter's default configuration of using an internal buffer,
83 * negatively impacting system health.
84 *
85 * @see flatMapLatest
86 */
87 fun <T, R> Flow<T>.flatMapLatestConflated(
88 @BuilderInference transform: suspend (T) -> Flow<R>,
89 ): Flow<R> = flatMapLatest(transform).conflate()
90
91 /**
92 * Returns a flow that produces element by [transform] function every time the original flow emits a
93 * value. When the original flow emits a new value, the previous `transform` block is cancelled,
94 * thus the name `transformLatest`.
95 *
96 * For example, the following flow:
97 * ```
98 * flow {
99 * emit("a")
100 * delay(100)
101 * emit("b")
102 * }.transformLatest { value ->
103 * emit(value)
104 * delay(200)
105 * emit(value + "_last")
106 * }
107 * ```
108 *
109 * produces `a b b_last`.
110 *
111 * This operator is [conflated][conflate] by default, and as such should be preferred over usage of
112 * [transformLatest], due to the latter's default configuration of using an internal buffer,
113 * negatively impacting system health.
114 *
115 * @see transformLatest
116 */
117 fun <T, R> Flow<T>.transformLatestConflated(
118 @BuilderInference transform: suspend FlowCollector<R>.(T) -> Unit,
119 ): Flow<R> = transformLatest(transform).conflate()
120