Skip to content

Commit 41dfc2b

Browse files
authored
Improve KDoc on StateFlowExtensions (#6338)
1 parent 7bfd4b5 commit 41dfc2b

1 file changed

Lines changed: 60 additions & 9 deletions

File tree

app/src/main/kotlin/com/x8bit/bitwarden/data/platform/repository/util/StateFlowExtensions.kt

Lines changed: 60 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,36 @@ import kotlinx.coroutines.flow.flow
1414
import kotlinx.coroutines.flow.map
1515

1616
/**
17-
* Invokes the [observer] callback whenever the user is logged in, the active changes, and there
18-
* are subscribers to the [MutableStateFlow]. The flow from all previous calls to the `observer`
19-
* is canceled whenever the `observer` is re-invoked, there is no active user (logged-out), or
20-
* there are no subscribers to the [MutableStateFlow].
17+
* Lazily invokes the [observer] callback with the active user's ID only when this MutableStateFlow
18+
* has external collectors and a user is logged in. Designed for operations that should only run
19+
* when UI actively observes the resulting data, but do not require the vault to be unlocked.
20+
*
21+
* **Active User Tracking:**
22+
* This function specifically tracks the active user from [userStateFlow]. When the active user
23+
* changes (e.g., account switching), the previous observer flow is canceled and a new one is
24+
* started for the new active user.
25+
*
26+
* **Subscription Detection:**
27+
* Uses [MutableStateFlow.subscriptionCount] to detect external collectors. Only external
28+
* `.collect()` calls increment subscriptionCount—internal flow operations (map, flatMapLatest,
29+
* update, etc.) do not affect it.
30+
*
31+
* **Common Pattern:**
32+
* ```kotlin
33+
* private val _triggerFlow = MutableStateFlow(Unit)
34+
* val dataFlow = _triggerFlow
35+
* .observeWhenSubscribedAndLoggedIn(userFlow) { activeUserId ->
36+
* repository.getData(activeUserId) // Only runs when dataFlow is collected
37+
* }
38+
* // _triggerFlow.update {} does NOT affect subscriptionCount
39+
* ```
40+
*
41+
* **Observer Lifecycle:**
42+
* - **Invoked** when subscriptionCount > 0 and a user is logged in
43+
* - **Re-invoked** when the active user changes (account switch)
44+
* - **Canceled** when subscribers disconnect or user logs out
45+
*
46+
* @see observeWhenSubscribedAndUnlocked for variant that also requires vault to be unlocked
2147
*/
2248
@OptIn(ExperimentalCoroutinesApi::class)
2349
fun <T, R> MutableStateFlow<T>.observeWhenSubscribedAndLoggedIn(
@@ -35,11 +61,36 @@ fun <T, R> MutableStateFlow<T>.observeWhenSubscribedAndLoggedIn(
3561
}
3662

3763
/**
38-
* Invokes the [observer] callback whenever the user is logged in, the active changes,
39-
* the vault for the user changes and there are subscribers to the [MutableStateFlow].
40-
* The flow from all previous calls to the `observer`
41-
* is canceled whenever the `observer` is re-invoked, there is no active user (logged-out),
42-
* there are no subscribers to the [MutableStateFlow] or the vault is not unlocked.
64+
* Lazily invokes the [observer] callback with the active user's ID only when this MutableStateFlow
65+
* has external collectors, a user is logged in, and the active user's vault is unlocked. Designed
66+
* for expensive operations that should only run when UI actively observes the resulting data.
67+
*
68+
* **Active User Tracking:**
69+
* This function specifically tracks the active user from [userStateFlow]. When the active user
70+
* changes (e.g., account switching), the previous observer flow is canceled and a new one is
71+
* started for the new active user. The vault unlock state is also tracked per-user.
72+
*
73+
* **Subscription Detection:**
74+
* Uses [MutableStateFlow.subscriptionCount] to detect external collectors. Only external
75+
* `.collect()` calls increment subscriptionCount—internal flow operations (map, flatMapLatest,
76+
* update, etc.) do not affect it.
77+
*
78+
* **Common Pattern:**
79+
* ```kotlin
80+
* private val _triggerFlow = MutableStateFlow(Unit)
81+
* val dataFlow = _triggerFlow
82+
* .observeWhenSubscribedAndUnlocked(userFlow, unlockFlow) { activeUserId ->
83+
* repository.getExpensiveData(activeUserId) // Only runs when dataFlow is collected
84+
* }
85+
* // _triggerFlow.update {} does NOT affect subscriptionCount
86+
* ```
87+
*
88+
* **Observer Lifecycle:**
89+
* - **Invoked** when subscriptionCount > 0, a user is logged in, and active user's vault unlocked
90+
* - **Re-invoked** when the active user changes (account switch) or vault state changes
91+
* - **Canceled** when subscribers disconnect, user logs out, or vault locks
92+
*
93+
* @see observeWhenSubscribedAndLoggedIn for variant without vault unlock requirement
4394
*/
4495
@OptIn(ExperimentalCoroutinesApi::class)
4596
fun <T, R> MutableStateFlow<T>.observeWhenSubscribedAndUnlocked(

0 commit comments

Comments
 (0)