代码之家  ›  专栏  ›  技术社区  ›  Cool

StateFlow未按预期收集

  •  0
  • Cool  · 技术社区  · 9 月前

    我正在做一个样本项目 fetchPosts 使用compose/clean体系结构 blog post :

    存储库包含:

    override fun getPosts(postId: Int): Flow<List<PostModel>>  = flow {
            val fromListDto = postMapper.fromListDto(postService.getPosts(postId).data)
            emit(fromListDto)
        }
    

    给我 viewModel :

    @HiltViewModel
    class PostViewModel @Inject constructor(
        private val postUseCase: GetPostUseCase
    ) : ViewModel() {
    
    
        private val _uiState = MutableStateFlow(PostUiState.Loading)
        val uiState: StateFlow<PostUiState> = _uiState.asStateFlow()
    
        fun fetchPosts() {
            viewModelScope.launch {
                postUseCase.invoke(0)
                    .asResult()
                    .map { result ->
                        when (result) {
                            is Result.Success -> PostUiState.Success(result.data)
                            is Result.Loading -> PostUiState.Loading
                            is Result.Error -> PostUiState.Error
                        }
                    }.stateIn(
                        scope = viewModelScope,
                        initialValue = PostUiState.Loading,
                        started = SharingStarted.WhileSubscribed(DEFAULT_TIMEOUT)
                    ).collect()
                }
    
            }
    }
    

    这是我的视图部分屏幕:

    @Composable
    fun PostScreen(
        navController: NavController,
        modifier: Modifier = Modifier,
        viewModel: PostViewModel = hiltViewModel()
    ) {
        LaunchedEffect(Unit) {
            viewModel.fetchPosts()
        }
    
        val uiState: PostUiState by viewModel.uiState.collectAsState()
    
        LazyVerticalGrid(
            columns = GridCells.Adaptive(100.dp),
            horizontalArrangement = Arrangement.spacedBy(8.dp),
            verticalArrangement = Arrangement.spacedBy(8.dp),
            contentPadding = PaddingValues(
                top = 16.dp,
                bottom = 16.dp
            )
        ) {
    
    
            when (val postState = uiState) {
                PostUiState.Error -> {
                    item(span = { GridItemSpan(maxLineSpan) }) {
                        Text(
                            "Error fetching posts",
                            modifier = Modifier
                                .padding(horizontal = 16.dp)
                        )
                    }
                }
    
                PostUiState.Loading -> {
                    item(span = { GridItemSpan(maxLineSpan) }) {
                        //LoadingIndicator()
                        Text(
                            "Loading ...",
                            modifier = Modifier
                                .padding(horizontal = 16.dp)
                        )
                    }
                }
    
                is PostUiState.Success -> {
                    items(postState.posts) { movie ->
                        PostImage(movie)
                    }
    
                    item(span = { GridItemSpan(maxLineSpan) }) {
                        Spacer(Modifier.height(16.dp))
                    }
                }
            }
        }
    }
    

    当我将我的viewModel更改为此(有效)时:

    fun fetchPosts() {
            viewModelScope.launch {
                postUseCase
                    .invoke(0)
                    //.asResult()
                    .collect { result ->
                        _uiState.value = GenreScreenUiState(PostUiState.Success(result))
    
                        }
    
                    }
    
            }
        }
    
    0 回复  |  直到 9 月前
        1
  •  0
  •   Cool    9 月前

    只是我没有观察到 flow 我在我的观点中观察到的,因此它需要这样:

    val uiState = postUseCase.invoke(0)
            .asResult()
            .map { result ->
                when (result) {
                    is Result.Success -> PostUiState.Success(result.data)
                    is Result.Loading -> PostUiState.Loading
                    is Result.Error -> PostUiState.Error
                }
            }.stateIn(
                scope = viewModelScope,
                initialValue = PostUiState.Loading,
                started = SharingStarted.WhileSubscribed(DEFAULT_TIMEOUT)
            )