1

代码 A 来自官方示例项目here

InterestsViewModel定义uiStateStateFlow,并在 Composable 函数中转换为State<T>as 。collectAsState()rememberTabContent

我很奇怪为什么作者没有直接在中 定义uiStateas ,所以我写了Code B。State<T>InterestsViewModel

Code B 可以编译,也可以运行,但是屏幕什么都没有,请问 Code B 有什么问题?

代码 A

data class InterestsUiState(
    val topics: List<InterestSection> = emptyList(),
    val people: List<String> = emptyList(),
    val publications: List<String> = emptyList(),
    val loading: Boolean = false,
)

class InterestsViewModel(
    private val interestsRepository: InterestsRepository
) : ViewModel() {

    // UI state exposed to the UI
    private val _uiState = MutableStateFlow(InterestsUiState(loading = true))
    val uiState: StateFlow<InterestsUiState> = _uiState.asStateFlow()
    ...
    init {
        refreshAll()
    }

    
    private fun refreshAll() {
        _uiState.update { it.copy(loading = true) }

        viewModelScope.launch {
             ...
            // Wait for all requests to finish
            val topics = topicsDeferred.await().successOr(emptyList())
            val people = peopleDeferred.await().successOr(emptyList())
            val publications = publicationsDeferred.await().successOr(emptyList())

            _uiState.update {
                it.copy(
                    loading = false,
                    topics = topics,
                    people = people,
                    publications = publications
                )
            }
        }
    }
 
}


@Composable
fun rememberTabContent(interestsViewModel: InterestsViewModel): List<TabContent> {
    // UiState of the InterestsScreen
    val uiState by interestsViewModel.uiState.collectAsState()
    ... 
    return listOf(topicsSection, peopleSection, publicationSection)
}


@Composable
fun InterestsRoute(
    interestsViewModel: InterestsViewModel,
    isExpandedScreen: Boolean,
    openDrawer: () -> Unit,
    scaffoldState: ScaffoldState = rememberScaffoldState()
) {
    val tabContent = rememberTabContent(interestsViewModel)
    val (currentSection, updateSection) = rememberSaveable {
        mutableStateOf(tabContent.first().section)
    }

    InterestsScreen(
        tabContent = tabContent,
        currentSection = currentSection,
        isExpandedScreen = isExpandedScreen,
        onTabChange = updateSection,
        openDrawer = openDrawer,
        scaffoldState = scaffoldState
    )
}

代码 B

data class InterestsUiState(
    val topics: List<InterestSection> = emptyList(),
    val people: List<String> = emptyList(),
    val publications: List<String> = emptyList(),
    var loading: Boolean = false,
)


class InterestsViewModel(
    private val interestsRepository: InterestsRepository
) : ViewModel() {
    
    // UI state exposed to the UI
    private var _uiState by mutableStateOf (InterestsUiState(loading = true))
    val uiState: InterestsUiState = _uiState

    ...
    
    init {
        refreshAll()
    }

    private fun refreshAll() {
        _uiState.loading = true

        viewModelScope.launch {
           ...
            _uiState = _uiState.copy(
                    loading = false,
                    topics = topics,
                    people = people,
                    publications = publications
                )
        }
    }

}

@Composable
fun rememberTabContent(interestsViewModel: InterestsViewModel): List<TabContent> {
    // UiState of the InterestsScreen
    val uiState = interestsViewModel.uiState
    ...
    return listOf(topicsSection, peopleSection, publicationSection)
}
4

1 回答 1

5

uiState您在 Composable 中使用的不是val uiState: InterestsUiState = _uiState状态,因此不会响应更改。它只是InterestsUiState用当前值初始化的正常值_uiState。为了让它工作,你可以简单地暴露 getter for _uiState

var uiState by mutableStateOf (InterestsUiState(loading = true))
    private set

现在这uiState只能从 ViewModel 内部修改,当你在 Composable 中使用它时,只要值发生uiState变化,就会发生重组。

于 2021-10-27T03:04:36.867 回答