Which Compose side-effect for a one-time coroutine action?

Tests if you can choose the right Compose side-effect for a one-time coroutine. A great answer names LaunchedEffect(Unit), explains it runs once and cancels on exit. A red flag is suggesting rememberCoroutineScope directly in the composable body.
What's really being asked
This question assesses your deep understanding of the Jetpack Compose side-effect system and its interaction with the composable lifecycle. The interviewer is looking for more than just naming an API; they want to see if you understand why a specific handler is correct, particularly concerning coroutine lifecycles, cancellation, and preventing redundant work during recomposition. It separates candidates who know the 'what' from those who know the 'why.'
The full answer
A senior-level answer should clearly and concisely hit four points in order. First, state that LaunchedEffect is the correct tool for this job. Second, specify using a constant key like Unit or true (LaunchedEffect(Unit) { ... }) to ensure the effect runs exactly once when the composable enters the composition, not on subsequent recompositions. Third, explain that LaunchedEffect provides a CoroutineScope, so you can directly call suspend functions. Fourth, highlight the critical safety feature: the coroutine is automatically cancelled when the LaunchedEffect leaves the composition, preventing memory leaks and orphaned network requests.
The mistakes people make
The most common and serious mistake is suggesting rememberCoroutineScope and then calling scope.launch directly within the main body of the composable function. This will launch a new coroutine on every single recomposition, potentially triggering thousands of network requests and crashing the app. Another incorrect answer is using SideEffect { ... }, which is meant for non-suspending code that needs to run after every successful recomposition. Using DisposableEffect is also suboptimal; its primary purpose is managing non-coroutine resources that require an explicit onDispose cleanup block, making LaunchedEffect the more idiomatic and safer choice for coroutine-based side effects.
What usually comes next
Be prepared for follow-ups like: 'What if you need the data to refetch when a user ID changes?' (Answer: Change the key from LaunchedEffect(Unit) to LaunchedEffect(userId)). 'When would you use rememberCoroutineScope instead?' (Answer: For launching coroutines in response to user events, like a button click, outside of the composition lifecycle). 'What's the difference between LaunchedEffect and produceState?' (Answer: produceState is for converting non-Compose state, like a Flow, into Compose State, while LaunchedEffect is for running general side-effect logic).
A concrete example
To fetch user profile data only once, you would write: LaunchedEffect(Unit) { val userProfile = viewModel.fetchUserProfile() }. The Unit key guarantees this fetchUserProfile() suspend function is called only when the composable is first added to the screen. If the composable is removed, any ongoing network request within that coroutine block is automatically cancelled by Compose.
Interview question
To fetch data from a network API exactly once when a composable first appears, which approach is correct and safe?
- a.Use `DisposableEffect(Unit)` to launch the coroutine and manage its cleanup in `onDispose`.
- b.Wrap the suspend function call inside a `LaunchedEffect(Unit)` block.Correct
- c.Use `rememberCoroutineScope()` and call `scope.launch` directly within the composable's body.
- d.Place the suspend function call within a `SideEffect` block to run it after composition.
Why? this is the answer
LaunchedEffect(Unit) is correct because it creates a coroutine that runs only once and is automatically cancelled on exit. Using `rememberCoroutineScope` directly in the composable body is a major error that launches a new coroutine on every recomposition.
Just read this? Test yourself on what you have been reading.
Read the original → developer.android.com
- #android
- #jetpack compose
- #coroutines
- #side-effects
You just looked this up. Could you explain it out loud?
That is the part interviews actually test. Tezvyn takes questions like this one and gives you what the interviewer is really checking, the answer that lands, and the mistake that ends the conversation, in the four minutes before your next meeting.
The iPhone app is on the way
We are building it. Until it lands, nothing here is held back from you: every interview card, your saved cards, streaks and the job board all work in Safari, plus hundreds of free practice quizzes of thirty questions each. Sign in and it all carries over to the app the day it arrives.
Want it as an icon? Tap Share at the bottom of Safari, then Add to Home Screen. It opens full screen and the cards you have read stay available offline.
We are hiring for this. Open roles that interview on android — each one lists the topics its interview covers.
See open roles