我正在创建一个显示项目列表的屏幕。这个项目列表来自互联网的分页响应,因此我尝试使用 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?
一种选择是当到达列表末尾时手动加载分页数据。所以不需要使用分页库