Follow the entire subscription chain. Lifecycle-aware UI collection can stop correctly while a ViewModel-owned shared stream continues running. Other subscribers or an eager sharing policy may keep its upstream active.
In a ViewModel, assuming observeLessons() returns a cold flow and Lesson is an existing type:
val lessons = repository.observeLessons().stateIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(5_000),
initialValue = emptyList<Lesson>()
)
The timeout gives a brief subscriber gap a chance to close before upstream collection stops. It is not a polling interval. A lifecycle-aware Compose collector can consume this state with collectAsStateWithLifecycle().
Log subscription and cancellation boundaries around the repository flow. Check all consumers, including analytics or another screen. Then inspect whether the repository wraps a hot producer whose lifetime is independent of this collection. Cancelling one downstream subscription cannot automatically shut down a globally owned socket.
Should every producer stop when the UI stops? No. An active user-requested operation may have a longer lifetime. Separate that operation from presentation and document who owns it. The goal is intentional resource ownership, not blindly cancelling all work on backgrounding.
Mark this when you can explain the answer in your own words.
Help fellow developers prepare for interviews
Sharing helps the Android community grow ๐