如何使用 UI State 数据类将流程实现到 Android MVI + Compose

问题描述 投票:0回答:1

我正在创建一个显示项目列表的屏幕。这个项目列表来自互联网的分页响应,因此我尝试使用 PagingData 和 Pager 来完成此操作,但只是找不到在维护 MVI 架构的同时将该流传递到可组合项的正确方法。

问题是我将 UIState 保存到 savingStateHandle 中,但我无法将流添加到 UIState 数据类,因为该流不可打包。

这是我的视图模型(缺少一些代码,但对于问题来说并不重要):

class PopularMoviesViewModel(
    savedStateHandle: SavedStateHandle,
    private val movieRepository: MovieRepository
) : ViewModel() {

    private val pageSize = 20

    data class UIState(
        val isLoading: Boolean,
        val movies: Flow<PagingData<Movie>>
    )

    private val _uiStateDelegate = ViewModelPropertyDelegate<PopularMoviesViewModel, UIState>(
        savedStateHandle,
        "uiState",
        UIState(
            false,
            flow {}
        )
    )
    private var _uiState by _uiStateDelegate
    val uiState = _uiStateDelegate.getStateFlow()

    sealed interface Action {
        class OnClickMovie(val movie: Movie) : Action
    }

    init {
        loadPopularMovies()
    }

    private fun loadPopularMovies() {
        _uiState = _uiState.copy(movies = Pager(
            config = PagingConfig(pageSize = pageSize),
            initialKey = 1,
            pagingSourceFactory = { movieRepository.getPopularMovies() }
        ).flow.cachedIn(viewModelScope))
    }
}

这是我的可组合项(这不是确切的代码,但你明白了):

@Composable
fun PopularMoviesComposable(
    uiState: PopularMoviesViewModel.UIState,
    doAction: (PopularMoviesViewModel.Action) -> Unit,
    modifier: Modifier = Modifier
) {
    Box(
        modifier = modifier
            .fillMaxSize()
            .padding(vertical = 48.dp, horizontal = 16.dp)
    ) {
        val movies = uiState.movies.collectAsLazyPagingItems()
        LazyVerticalGrid(
            columns = GridCells.Adaptive(128.dp),
            verticalArrangement = Arrangement.spacedBy(16.dp),
            horizontalArrangement = Arrangement.spacedBy(12.dp)
        ) {
            items(movies.itemCount)
            { index ->
                movies[index]?.let {
                    MovieCard(
                        movie = it,
                        onClickMovie = {doAction(PopularMoviesViewModel.Action.OnClickMovie(it))}
                    )
                }
            }
        }
    }
}

正如您所看到的,可组合项没有获取视图模型作为参数,而是获取 UIState,所以问题是

如果 UIState 类中有一个流,是否可以有一个像这样的 UIState 类的可组合项?

抱歉英语不好。

我知道我可以将视图模型注入可组合项中,而不是使用 UIState,然后从那里获取我需要的一切。问题是,在测试可组合项和视图模型时,我发现这种使用 UIState 数据类的方法更容易实现。

也许方法本身不正确并且我没有正确理解MVI?

android kotlin architecture android-jetpack-compose
1个回答
0
投票

一种选择是当到达列表末尾时手动加载分页数据。所以不需要使用分页库

最新问题
© www.soinside.com 2019 - 2024. All rights reserved.