能否在代码A之外的地方更改uiStateA的值?

huangapple go评论62阅读模式
英文:

Can val uiStateA be changed outside ViewModel in Code A?

问题

I know that asStateFlow()将可将可变状态流表示为只读状态流,所以我认为val uiStateB不能在 Code B 中的 InterestsViewModel 外部更改,这是一个不错的方式。

val uiStateA是由 combine 生成的,可以在 Code A 中的 TaskDetailViewModel 外部更改吗?如果可以,Code A 是否是一个好的方式?

Code A

class TaskDetailViewModel @Inject constructor(
    ...
) : ViewModel() {
  
    private val _userMessage: MutableStateFlow<Int?> = MutableStateFlow(null)
    private val _isLoading = MutableStateFlow(false)
    private val _isTaskDeleted = MutableStateFlow(false)
    private val _taskAsync = taskRepository.getTaskStream(taskId)
    
   val uiStateA: StateFlow<TaskDetailUiState> = combine(
       _userMessage, _isLoading, _isTaskDeleted, _taskAsync
    ) { userMessage, isLoading, isTaskDeleted, taskAsync ->
       when (taskAsync) {
          ...
       }
   } .stateIn(
       scope = viewModelScope,
       started = WhileUiSubscribed,
       initialValue = TaskDetailUiState(isLoading = true)
   )
}

Code B

class InterestsViewModel(
    private val interestsRepository: InterestsRepository
) : ViewModel() {
 
    private val _uiState = MutableStateFlow(InterestsUiState(loading = true))
    val uiStateB: StateFlow<InterestsUiState> = _uiState.asStateFlow()
    ...
}
英文:

I know that asStateFlow() will represent a mutable state flow as a read-only state flow, so I think the val uiStateB can't be changed outside InterestsViewModel in Code B, it's a good way.

val uiStateA is generated by combine, can val uiStateA be changed outside TaskDetailViewModel in Code A ? If so, is the Code A good way?

Code A

class TaskDetailViewModel @Inject constructor(
    ...
) : ViewModel() {
  
    private val _userMessage: MutableStateFlow<Int?> = MutableStateFlow(null)
    private val _isLoading = MutableStateFlow(false)
    private val _isTaskDeleted = MutableStateFlow(false)
    private val _taskAsync = taskRepository.getTaskStream(taskId)
    
   val uiStateA: StateFlow<TaskDetailUiState> = combine(
       _userMessage, _isLoading, _isTaskDeleted, _taskAsync
    ) { userMessage, isLoading, isTaskDeleted, taskAsync ->
       when (taskAsync) {
          ...
       }
   } .stateIn(
       scope = viewModelScope,
       started = WhileUiSubscribed,
       initialValue = TaskDetailUiState(isLoading = true)
   )
}

Code B

class InterestsViewModel(
    private val interestsRepository: InterestsRepository
) : ViewModel() {
 
    private val _uiState = MutableStateFlow(InterestsUiState(loading = true))
    val uiStateB: StateFlow<InterestsUiState> = _uiState.asStateFlow()
    ...
}

答案1

得分: 1

No. Vals 只能在初始化时设置一次。之后尝试更改它们将导致编译错误。如果您想要更改它(我不建议这样做,这将是一种尴尬的架构并可能引发错误),您可以使用 var。

但是值仍然可以发送到 StateFlow。因此,如果代码使用 uiStateA.value,它们将获得不同的值,因为它组合的流发生变化。

英文:

No. Vals can only be set once, at initialization. After that, attempting to change them will cause a compile error. If you want to change it (which I would not recommend, it would be an awkward architecture and open up bugs) you'd use a var instead.

However values can still be emitted to the stateflow. So if code did uiStateA.value they would get different values as the flows it combines change.

答案2

得分: 1

stateIn创建了一个无法转换为MutableStateFlow的StateFlow,就像asStateFlow()一样。因此,您不能通过uiStateA引用更改value或正在发射的内容。(除非通过可以实现几乎任何操作的反射。)

英文:

stateIn creates a StateFlow that cannot be cast to MutableStateFlow, just like asStateFlow() does. Therefore you cannot change the value or what’s being emitted using the uiStateA reference. (Except through reflection which can achieve pretty much anything.)

huangapple
  • 本文由 发表于 2023年6月6日 10:24:27
  • 转载请务必保留本文链接:https://go.coder-hub.com/76411065.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定