State hoisting means moving state from a child composable to its parent so the parent controls the state. This helps keep UI components reusable and testable.
Click to reveal answer
beginner
Why do we use state hoisting in Jetpack Compose?
We use state hoisting to separate UI from state management. It makes components simpler and easier to reuse because they don’t hold their own state internally.
Click to reveal answer
intermediate
In state hoisting, what are the two main parts of a composable function?
One part is the state holder (usually in the parent) that owns and updates the state. The other is the stateless UI (child composable) that displays data and sends events back.
Click to reveal answer
intermediate
How does state hoisting improve testability?
By moving state outside the UI, you can test the UI with fixed inputs and test the state logic separately. This separation makes tests simpler and clearer.
Click to reveal answer
beginner
What Kotlin language feature helps implement state hoisting in Compose?
The MutableState and State types along with remember and by delegation help hold and observe state changes in Compose.
Click to reveal answer
What is the main benefit of state hoisting in Jetpack Compose?
AAutomatically saves state to disk
BRemoves the need for state in the app
CMakes UI components reusable and easier to test
DAllows UI to update without any state
✗ Incorrect
State hoisting moves state control to the parent, making UI components reusable and testable.
In state hoisting, who owns the state?
AThe parent composable
BThe child composable
CThe Android system
DNo one owns the state
✗ Incorrect
The parent composable owns and controls the state in state hoisting.
Which Kotlin type is commonly used to hold state in Compose?
AString
BList
CMap
DMutableState
✗ Incorrect
MutableState holds state that Compose can observe and react to.
What does the child composable do in state hoisting?
ADisplays UI and sends events to parent
BManages and updates the state
CStores data in a database
DHandles navigation between screens
✗ Incorrect
The child composable is stateless and only displays UI and sends events back to the parent.
Which Compose function helps remember state across recompositions?
Alaunch
Bremember
CcollectAsState
DproduceState
✗ Incorrect
remember keeps state during recompositions in Compose.
Explain the state hoisting pattern and why it is useful in Jetpack Compose.
Think about who controls the state and how UI components communicate.
You got /4 concepts.
Describe how you would implement state hoisting for a simple text input field in Compose.
Consider passing state and event handlers as parameters.
You got /3 concepts.
Practice
(1/5)
1. What is the main purpose of state hoisting in Android Kotlin UI development?
easy
A. To avoid using ViewModel for state management
B. To keep all state inside UI components for faster rendering
C. To make UI components dependent on global variables
D. To move state out of UI components to make them simpler and reusable
Solution
Step 1: Understand state hoisting concept
State hoisting means moving state out of UI components so they don't manage their own state internally.
Step 2: Identify the benefit of moving state out
This makes UI components simpler, easier to reuse, and testable by passing state and events as parameters.
Final Answer:
To move state out of UI components to make them simpler and reusable -> Option D
Quick Check:
State hoisting = move state out [OK]
Hint: State hoisting means lifting state up from UI [OK]
Common Mistakes:
Thinking state should stay inside UI components
Confusing state hoisting with global variables
Believing ViewModel is not related to state hoisting
2. Which of the following is the correct way to pass state to a composable function following the state hoisting pattern?
easy
A. fun Greeting() { var name = "John"; Text("Hello $name") }
B. fun Greeting() { val name = remember { mutableStateOf("John") }; Text("Hello ${name.value}") }
C. fun Greeting(name: String) { Text("Hello $name") }
D. fun Greeting() { Text("Hello") }
Solution
Step 1: Identify state hoisting signature
State hoisting means the composable receives state as a parameter instead of owning it internally.
Step 2: Check which function receives state as parameter
fun Greeting(name: String) { Text("Hello $name") } passes name: String as parameter, which is correct for hoisting state.
Final Answer:
fun Greeting(name: String) { Text("Hello $name") } -> Option C
Quick Check:
State passed as parameter = fun Greeting(name: String) { Text("Hello $name") } [OK]
Hint: State hoisted means passed as parameter, not created inside [OK]
Common Mistakes:
Creating state inside composable instead of passing it
Not passing state at all
Using remember inside UI component for hoisted state
3. Given the following code, what will be the output when the button is clicked once?
var count by remember { mutableStateOf(0) }
Button(onClick = { count++ }) {
Text("Clicked $count times")
}
medium
A. Clicked 1 times
B. Clicked 0 times
C. Clicked times
D. Runtime error
Solution
Step 1: Understand initial state value
The variable count starts at 0 using remember and mutableStateOf.
Step 2: Analyze button click effect
When the button is clicked once, count++ increments count to 1, triggering recomposition.
Final Answer:
Clicked 1 times -> Option A
Quick Check:
Initial 0 + 1 click = 1 [OK]
Hint: Increment state on click updates UI text [OK]
Common Mistakes:
Thinking count stays 0 after click
Ignoring recomposition after state change
Expecting syntax or runtime error
4. Identify the error in this state hoisting example:
@Composable
fun Counter() {
var count by remember { mutableStateOf(0) }
CounterDisplay(count)
}
@Composable
fun CounterDisplay(count: Int) {
Button(onClick = { count++ }) {
Text("Count: $count")
}
}
medium
A. count++ inside CounterDisplay does not update state in Counter
B. Button onClick should not modify count at all
C. remember should be used inside CounterDisplay instead
D. State should be mutable in CounterDisplay to increment
Solution
Step 1: Analyze state ownership and mutation
State count is owned in Counter and passed as immutable Int to CounterDisplay.
Step 2: Understand why count++ in CounterDisplay fails
Incrementing count inside CounterDisplay only changes local copy, not the original state in Counter.
Final Answer:
count++ inside CounterDisplay does not update state in Counter -> Option A
Quick Check:
Immutable parameter can't update hoisted state [OK]
Hint: Only owner can update hoisted state, not parameter [OK]
Common Mistakes:
Trying to mutate immutable parameter
Using remember in child composable incorrectly
Not passing event callback to update state
5. How should you modify the following code to correctly implement state hoisting so that CounterDisplay can update the count?
@Composable
fun Counter() {
var count by remember { mutableStateOf(0) }
CounterDisplay(count)
}
@Composable
fun CounterDisplay(count: Int) {
Button(onClick = { count++ }) {
Text("Count: $count")
}
}
hard
A. Make count a var inside CounterDisplay and increment it there
B. Pass a lambda to CounterDisplay to update count in Counter
C. Use remember { mutableStateOf(0) } inside CounterDisplay instead
D. Remove count parameter and manage state only in CounterDisplay
Solution
Step 1: Recognize state hoisting requires event callbacks
To update hoisted state, child composable must receive a function to trigger state changes in the owner.
Step 2: Modify CounterDisplay to accept update lambda
Pass a lambda like onCountChange: () -> Unit to CounterDisplay and call it inside onClick.
Final Answer:
Pass a lambda to CounterDisplay to update count in Counter -> Option B
Quick Check:
State hoisting needs event callback to update state [OK]
Hint: Pass update function down to child to change hoisted state [OK]
Common Mistakes:
Trying to mutate parameter directly
Creating new state inside child composable
Removing state from owner composable
Recommended
Ready to prove it?
Pass the test and this pattern moves unknownstrongwhile earning +1 Grip toward your certificate.