为什么我使用 MutableStateFlow 时需要在 Compose UI 中调用 collect?
Why do I need invoke collect in Compose UI when I use MutableStateFlow?
我看过Android官方artical.
我看到 MutableStateFlow
很热 Flow
并且被 Compose 观察到在它们发生变化时触发重组。
代码A来自Android官方文章,没关系。
我很奇怪为什么作者需要调用 collect
来获取代码 A 中 Compose UI 的最新值。
我认为 Compose UI 总能得到 latestNewsViewModel.uiState
的最新值,为什么我不能使用代码 B 做同样的工作?
代码A
class LatestNewsActivity : AppCompatActivity() {
private val latestNewsViewModel = // getViewModel()
override fun onCreate(savedInstanceState: Bundle?) {
...
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
latestNewsViewModel.uiState.collect { uiState ->
when (uiState) {
is LatestNewsUiState.Success -> showFavoriteNews(uiState.news)
is LatestNewsUiState.Error -> showError(uiState.exception)
}
}
}
}
}
}
class LatestNewsViewModel(
private val newsRepository: NewsRepository
) : ViewModel() {
private val _uiState = MutableStateFlow(LatestNewsUiState.Success(emptyList()))
val uiState: StateFlow<LatestNewsUiState> = _uiState
init {
viewModelScope.launch {
newsRepository.favoriteLatestNews
.collect { favoriteNews ->
_uiState.value = LatestNewsUiState.Success(favoriteNews)
}
}
}
}
代码B
class LatestNewsActivity : ComponentActivity() {
private val latestNewsViewModel = // getViewModel()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
SoundMeterTheme {
Surface(color = MaterialTheme.colors.background) {
Greeting(latestNewsViewModel)
}
}
}
}
}
@Composable
fun Greeting(latestNewsViewModel: LatestNewsViewModel) {
val myUIState by remember{ latestNewsViewModel.uiState }
when (myUIState) {
is LatestNewsUiState.Success -> showFavoriteNews(uiState.news)
is LatestNewsUiState.Error -> showError(uiState.exception)
}
}
//The same
添加内容
致 RaBaKa 78:谢谢!
根据您的意见,我可以使用代码 C 代替代码 A 吗?
代码C
class LatestNewsActivity : ComponentActivity() {
private val latestNewsViewModel = // getViewModel()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
SoundMeterTheme {
Surface(color = MaterialTheme.colors.background) {
Greeting(latestNewsViewModel)
}
}
}
}
}
@Composable
fun Greeting(latestNewsViewModel: LatestNewsViewModel) {
val myUIState by remember{ latestNewsViewModel.uiState.collectAsState() }
when (myUIState) {
is LatestNewsUiState.Success -> showFavoriteNews(uiState.news)
is LatestNewsUiState.Error -> showError(uiState.exception)
}
}
//The same
Compose 需要 State
而不是 StateFlow
进行相应的重组,
您可以在 compose
中轻松地将 StateFlow
转换为 State
val myUiState = latestNewsViewModel.uiState.collectAsState()
不需要使用 remember {}
因为你的 StateFlow
来自你的 viewModel
,所以它可以在没有 remember
的情况下管理重组
因此,与代码 B 一样,您可以手动 检查 StateFLow
的状态或自动转换为 State
和 [=38] =] 当状态改变时重组。
代码 A 是 XML 做事的方式,您可以在其中调用其他函数,但在 Compose
中,您应该在 viewModel
中执行该步骤
代码 D
class LatestNewsViewModel(
private val newsRepository: NewsRepository
) : ViewModel() {
private val _uiState = MutableStateFlow(LatestNewsUiState.Success(emptyList()))
val uiState: StateFlow<LatestNewsUiState> = _uiState
init {
viewModelScope.launch {
newsRepository.favoriteLatestNews
.collect { favoriteNews ->
_uiState.value = LatestNewsUiState.Success(favoriteNews)
}
}
}
}
@Composable
fun Greeting(latestNewsViewModel: LatestNewsViewModel) {
val myUIState = latestNewsViewModel.uiState.collectAsState()
Column(modifier = Modifier.fillMaxSIze()) {
when(myUIState) {
is LatestNewsUiState.Success -> SuccessComposable(uiState.news)
is LatestNewsUiState.Error -> showError(uiState.exception) -> ErrorComposable(uiState.exception)
}
}
}
我看过Android官方artical.
我看到 MutableStateFlow
很热 Flow
并且被 Compose 观察到在它们发生变化时触发重组。
代码A来自Android官方文章,没关系。
我很奇怪为什么作者需要调用 collect
来获取代码 A 中 Compose UI 的最新值。
我认为 Compose UI 总能得到 latestNewsViewModel.uiState
的最新值,为什么我不能使用代码 B 做同样的工作?
代码A
class LatestNewsActivity : AppCompatActivity() {
private val latestNewsViewModel = // getViewModel()
override fun onCreate(savedInstanceState: Bundle?) {
...
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
latestNewsViewModel.uiState.collect { uiState ->
when (uiState) {
is LatestNewsUiState.Success -> showFavoriteNews(uiState.news)
is LatestNewsUiState.Error -> showError(uiState.exception)
}
}
}
}
}
}
class LatestNewsViewModel(
private val newsRepository: NewsRepository
) : ViewModel() {
private val _uiState = MutableStateFlow(LatestNewsUiState.Success(emptyList()))
val uiState: StateFlow<LatestNewsUiState> = _uiState
init {
viewModelScope.launch {
newsRepository.favoriteLatestNews
.collect { favoriteNews ->
_uiState.value = LatestNewsUiState.Success(favoriteNews)
}
}
}
}
代码B
class LatestNewsActivity : ComponentActivity() {
private val latestNewsViewModel = // getViewModel()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
SoundMeterTheme {
Surface(color = MaterialTheme.colors.background) {
Greeting(latestNewsViewModel)
}
}
}
}
}
@Composable
fun Greeting(latestNewsViewModel: LatestNewsViewModel) {
val myUIState by remember{ latestNewsViewModel.uiState }
when (myUIState) {
is LatestNewsUiState.Success -> showFavoriteNews(uiState.news)
is LatestNewsUiState.Error -> showError(uiState.exception)
}
}
//The same
添加内容
致 RaBaKa 78:谢谢!
根据您的意见,我可以使用代码 C 代替代码 A 吗?
代码C
class LatestNewsActivity : ComponentActivity() {
private val latestNewsViewModel = // getViewModel()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
SoundMeterTheme {
Surface(color = MaterialTheme.colors.background) {
Greeting(latestNewsViewModel)
}
}
}
}
}
@Composable
fun Greeting(latestNewsViewModel: LatestNewsViewModel) {
val myUIState by remember{ latestNewsViewModel.uiState.collectAsState() }
when (myUIState) {
is LatestNewsUiState.Success -> showFavoriteNews(uiState.news)
is LatestNewsUiState.Error -> showError(uiState.exception)
}
}
//The same
Compose 需要 State
而不是 StateFlow
进行相应的重组,
您可以在 compose
中轻松地将StateFlow
转换为 State
val myUiState = latestNewsViewModel.uiState.collectAsState()
不需要使用 remember {}
因为你的 StateFlow
来自你的 viewModel
,所以它可以在没有 remember
因此,与代码 B 一样,您可以手动 检查 StateFLow
的状态或自动转换为 State
和 [=38] =] 当状态改变时重组。
代码 A 是 XML 做事的方式,您可以在其中调用其他函数,但在 Compose
中,您应该在 viewModel
代码 D
class LatestNewsViewModel(
private val newsRepository: NewsRepository
) : ViewModel() {
private val _uiState = MutableStateFlow(LatestNewsUiState.Success(emptyList()))
val uiState: StateFlow<LatestNewsUiState> = _uiState
init {
viewModelScope.launch {
newsRepository.favoriteLatestNews
.collect { favoriteNews ->
_uiState.value = LatestNewsUiState.Success(favoriteNews)
}
}
}
}
@Composable
fun Greeting(latestNewsViewModel: LatestNewsViewModel) {
val myUIState = latestNewsViewModel.uiState.collectAsState()
Column(modifier = Modifier.fillMaxSIze()) {
when(myUIState) {
is LatestNewsUiState.Success -> SuccessComposable(uiState.news)
is LatestNewsUiState.Error -> showError(uiState.exception) -> ErrorComposable(uiState.exception)
}
}
}