Paging 3 列表在 Jetpack Compose 导航返回导航时自动刷新

Paging 3 list auto refresh on navigation back in jetpack compose navigation

我正在使用 Jetpack Compose,以及 Paging 3 库和 Jetpack Navigation。我面临的问题是我有一个 LazyList,它使用分页库从远程源获取数据。

ViewModel

fun getImages(): Flow<PagingData<ObjectImage>> = Pager(
        PagingConfig(PAGE_SIZE, enablePlaceholders = false)
    ) { DataHome(RANDOM) }.flow.cachedIn(viewModelScope)

主页视图

val images = viewModelHome.getImages().collectAsLazyPagingItems()
LazyColumn {
  ...
}

现在发生的事情是当我使用 navHostController.navigate() 导航到另一个视图,然后按返回键返回主视图... LazyColumn 会自行重置并再次开始从网络加载项目。

所以我被这个问题困住了。我尝试在 viewModel 变量中手动缓存...虽然它有效但它搞砸了 SwipeRefresh(停止显示刷新状态)

data.apply {
            when {
                // refresh
                loadState.refresh is LoadState.Loading -> {
                    ItemLoading()
                }

                // reload
                loadState.append is LoadState.Loading -> {...}

                // refresh error
                loadState.refresh is LoadState.Error -> {...}

                // reload error
                loadState.append is LoadState.Error -> {...}
            }
        }
implementation("androidx.paging:paging-runtime-ktx:3.1.0")
implementation("androidx.paging:paging-compose:1.0.0-alpha14")

这是仍处于 alpha 阶段的 PagingLibrary 的问题吗??

Update 1 (I am not sure if this is a good solution, but I am solving the swipe refresh issue as follows)

// get images
    var images: Flow<PagingData<ObjectImage>> = Pager(PagingConfig(PAGE_SIZE)) {
        DataHome(RANDOM)
    }.flow.cachedIn(viewModelScope)

    // reload items
    fun reload(){
        images = Pager(PagingConfig(PAGE_SIZE)) {
            DataHome(RANDOM)
        }.flow.cachedIn(viewModelScope)
    }

// and rather than calling .refresh() method on lazy items... I am calling viewModel.reload()

问题是您每次调用 getImages() 时都会创建新的 Pager,也就是每次您的可组合项重新组合时,这不是应该的方式。

您应该将其设置为 val items = Pager(... 以便缓存工作。

对于搞砸的SwipeRefresh,你是如何实现的? LazyPagingItems 上有一个 refresh() 方法,你应该使用它。


编辑:好的,根据对您问题的评论和编辑:

在您的视图模型中,按照我之前的建议进行操作:

val items = Pager( // define your pager here

您的可组合项可以如下所示:

@Composable
fun Screen() {
    val items = viewModel.items.collectAsLazyPagingItems()
    val state = rememberSwipeRefreshState(
        isRefreshing = items.loadState.refresh is LoadState.Loading,
    )

    SwipeRefresh(
        modifier = Modifier.fillMaxSize(),
        state = state,
        // use the provided LazyPagingItems.refresh() method,
        // no need for custom solutions
        onRefresh = { items.refresh() }
    ) {
        LazyColumn(
            modifier = Modifier.fillMaxSize(),
        ) {
            // display the items only when loadState.refresh is not loading,
            // as you wish
            if (items.loadState.refresh is LoadState.NotLoading) {
                items(items) {
                    if (it != null) {
                        Text(
                            modifier = Modifier.padding(16.dp),
                            text = it,
                        )
                    }
                }
                // you can also add item for LoadState.Error, anything you want
                if (items.loadState.append is LoadState.Loading) {
                    item {
                        Box(modifier = Modifier.fillMaxWidth()) {
                            CircularProgressIndicator(
                                modifier = Modifier
                                    .align(Alignment.Center)
                                    .padding(16.dp)
                            )
                        }
                    }
                }
            }
            // if the loadState.refresh is Loading,
            // display just single loading item,
            // or nothing at all (SwipeRefresh already indicates
            // refresh is in progress)
            else if (items.loadState.refresh is LoadState.Loading) {
                item {
                    Box(modifier = Modifier.fillParentMaxSize()) {
                        Text(
                            text = "Refreshing",
                            modifier = Modifier.align(Alignment.Center))
                    }
                }
            }
        }
    }
}