You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Composable页面间共享ViewModel失效:跨页面修改并观察mutableStateOf<Boolean>不生效

Jetpack Compose: State not updating between screens with Hilt ViewModel

Ah, I see exactly what's going on here! The root issue is that Screen1 and Screen2 are creating separate instances of MyViewModel, so when you update the state in Screen2, it doesn't affect the instance Screen1 is observing.

Why this happens

By default, the hiltViewModel() function uses the ViewModelStoreOwner tied to the current navigation destination. Each screen in Jetpack Navigation gets its own dedicated ViewModelStore, which means your two screens end up with completely separate ViewModel instances. Modifying one has no impact on the other.

Fix 1: Share the ViewModel across your navigation graph

If both screens live under the same navigation graph, you can fetch the ViewModel tied to the graph's ViewModelStoreOwner instead of individual destinations. This guarantees both screens use the same instance:

Updated Screen1:

@Composable
fun Screen1(navigate: () -> Unit) {
    val navController = LocalNavController.current
    // Fetch ViewModel linked to the entire navigation graph
    val vm: MyViewModel = hiltViewModel(navController.graph)
    
    val myTestBoolean = vm.testBoolean.value
    Column {
        // Added an else branch so you can see the initial false state clearly
        Text(text = "myTestBoolean is $myTestBoolean")
        Button(onClick = navigate) {
            Text(text = "Navigate to Screen2")
        }
    }
}

Updated Screen2:

@Composable
fun Screen2(navigate: () -> Unit) {
    val navController = LocalNavController.current
    val vm: MyViewModel = hiltViewModel(navController.graph)
    
    Button(onClick = {
        vm.setTestBoolean(true)
        navigate()
    }) {
        Text(text = "Back")
    }
}

Fix 2: Tie the ViewModel to your Activity

If you want the ViewModel to be shared across your entire single-Activity app, you can use the Activity itself as the ViewModelStoreOwner:

Screen1:

@Composable
fun Screen1(navigate: () -> Unit) {
    val activity = LocalActivity.current
    val vm: MyViewModel = hiltViewModel(activity)
    
    val myTestBoolean = vm.testBoolean.value
    Column {
        Text(text = "myTestBoolean is $myTestBoolean")
        Button(onClick = navigate) {
            Text(text = "Navigate to Screen2")
        }
    }
}

Screen2:

@Composable
fun Screen2(navigate: () -> Unit) {
    val activity = LocalActivity.current
    val vm: MyViewModel = hiltViewModel(activity)
    
    Button(onClick = {
        vm.setTestBoolean(true)
        navigate()
    }) {
        Text(text = "Back")
    }
}

Bonus: Make your ViewModel more secure

Right now you're exposing testBoolean as a MutableState, which lets external code modify the state directly. For better encapsulation, switch to exposing an immutable State instead:

@HiltViewModel
class MyViewModel @Inject constructor() : ViewModel() {
    private val _testBoolean = mutableStateOf(false)
    // Expose immutable State instead of MutableState
    val testBoolean: State<Boolean> = _testBoolean
    
    fun setTestBoolean(boolean: Boolean){
        _testBoolean.value = boolean
    }
}

This way, the only way to update the state is through the setTestBoolean method, keeping your state logic controlled and predictable.

内容的提问来源于stack exchange,提问作者HavanaSun

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 18:47:34