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

Jetpack Compose组件间数据共享问题:ProfileScreen无法获取数据

问题排查与解决:Jetpack Compose组件间SharedViewModel数据为空

问题根源

  1. ViewModel实例不共享:在EmployeeSettingsViewModel中,你手动通过SharedViewModel(employeeSettingsModel)创建了ViewModel实例,这会完全绕过Hilt的依赖注入管理,导致这个实例和BottomNavigationScreen、ProfileScreen中通过hiltViewModel()获取的SharedViewModel不是同一个对象——两边操作的是不同内存空间,数据自然无法同步。
  2. 数据更新逻辑无效:由于操作的是独立的ViewModel实例,你在EmployeeSettingsViewModel中调用setSharedData时,修改的只是本地新建实例的 data,而非全局共享的那个。

解决步骤与代码修正

1. 修正EmployeeSettingsViewModel:通过Hilt注入SharedViewModel

删除手动实例化代码,改为构造函数注入SharedViewModel,确保使用同一全局实例:

@HiltViewModel
class EmployeeSettingsViewModel @Inject constructor(
    employeeSettingsModel: EmployeeSettingsModel,
    private val commonViewModel: CommonViewModel,
    private val authRepository: AuthRepository,
    private val realtimeDatabaseViewModel: RealTimeDatabaseViewModel,
    private val cypherInstance: CryptoClass,
    // 注入SharedViewModel,替代手动实例化
    private val sharedViewModel: SharedViewModel
) : ViewModel() {

    companion object {
        private const val TAG = "EmployeeSettingsViewModel"
        private val SECURITYLIST = listOf("phoneNumber", "email", "age", "name")
    }

    private val _uiState = MutableStateFlow(employeeSettingsModel)
    val uiState: StateFlow<EmployeeSettingsModel> = _uiState.asStateFlow()

    fun setSharedData(employeeSettingsModel: EmployeeSettingsModel) {
        sharedViewModel.setSharedData(employeeSettingsModel)
    }
    ... 
}

2. 确保SharedViewModel的全局单例作用域

为让多个屏幕共享同一实例,给SharedViewModel添加@Singleton注解,Hilt会确保整个应用生命周期内只有一个实例:

@HiltViewModel
@Singleton
class SharedViewModel @Inject constructor(
    employeeSettingsModel: EmployeeSettingsModel
) : ViewModel() {

    private val _sharedData = MutableStateFlow(employeeSettingsModel)
    val sharedData: StateFlow<EmployeeSettingsModel> get() = _sharedData.asStateFlow()

    fun setSharedData(data: EmployeeSettingsModel) {
        // 修正打印逻辑,打印更新后的data字段
        println("SharedViewModel: ${data.country}")
        _sharedData.value = data
    }
}

3. 确保数据同步触发

在EmployeeSettingsScreen中,完成EmployeeSettingsModel更新后,必须调用employeeSettingsViewModel.setSharedData(updatedModel),将最新数据同步到SharedViewModel:

@Composable
fun EmployeeSettingsScreen() {
    val employeeSettingsViewModel: EmployeeSettingsViewModel = hiltViewModel()
    val commonViewModel: CommonViewModel = hiltViewModel()
    val commonUiState: CommonModel by commonViewModel.uiState.collectAsState()
    val uiState by employeeSettingsViewModel.uiState.collectAsState()

    // 示例:用户提交表单时同步数据到SharedViewModel
    Button(onClick = {
        val updatedModel = uiState.copy(
            name = "新名字",
            email = "new@email.com"
            // 其他字段更新逻辑
        )
        employeeSettingsViewModel.setSharedData(updatedModel)
    }) {
        Text("保存并同步到Profile")
    }
    ... 
}

4. 验证ProfileScreen的数据收集

ProfileScreen代码无需大改,确保通过hiltViewModel()获取全局单例的SharedViewModel即可:

@Composable
fun ProfileScreen() {
    val sharedViewModel: SharedViewModel = hiltViewModel()
    val sharedData by sharedViewModel.sharedData.collectAsState()

    val commonViewModel: CommonViewModel = hiltViewModel()

    val uiState by when (LoggedInUser.registrationType.value) {
        "employee" -> sharedViewModel.sharedData
        else -> throw IllegalStateException("Invalid user type")
    }.collectAsState()

    LaunchedEffect(sharedData) {
        println("The sharedData is currently $sharedData")
    }

    // 用sharedData渲染UI
    Column {
        Text("姓名:${sharedData.name}")
        Text("邮箱:${sharedData.email}")
    }
    ... 
}

补充说明

如果仅需在BottomNavigationScreen下的子页面间共享数据,而非全局共享,可以不用@Singleton,而是在获取ViewModel时指定NavGraph作用域:

// 在BottomNavigationScreen中获取NavGraph作用域的ViewModel
val sharedViewModel: SharedViewModel = hiltViewModel(navController.graph)

// 在子页面(EmployeeSettingsScreen、ProfileScreen)中同样使用NavGraph作用域获取
val sharedViewModel: SharedViewModel = hiltViewModel(navController = rememberNavController())

这种方式更符合组件化的作用域管理,避免全局单例的过度使用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 03:54:55