如何使用新的Paging库实现SwipeRefreshLayout

17

我有一个活动,向用户展示一系列项目的列表,并使用了Paging Library。我的问题是,当用户向下滑动屏幕以使其再次从服务器获取数据时,我无法重新加载该列表。

这是我的数据源工厂:

public class CouponListDataSourceFactory extends DataSource.Factory {
    private CouponListDataSource dataSource;

    public CouponListDataSourceFactory(CouponRepository repository, String token, String vendorId) {
        dataSource = new CouponListDataSource(repository, token, vendorId);
    }

    @Override
    public DataSource create() {
        return dataSource;
    }
}

这里是我创建PagedList的方法

PagedList.Config config = new PagedList.Config.Builder()
                .setInitialLoadSizeHint(15)
                .setPageSize(10)
                .build();
LiveData<PagedList<Coupon>> couponsLiveData = new LivePagedListBuilder<>(dataSourceFactory, config).build();

只需使您的自定义“DataSource”无效,您有哪些“DataSource”? - pskink
@pskink 我使用PositionalDataSource。我在我的数据源上调用invalidate方法,但它没有任何作用。在使其无效后,我还需要做其他事情吗? - Mostafa
你使用过 PagedListAdapter 吗?你的代码是什么样子的?PagedList#isDetached() 返回什么? - pskink
是的,我使用LivePagedListBuilder创建它,并将其从我的viewmodel返回到我的activity。 - Mostafa
谢谢你的回答。我想我的错误在于我总是在create()方法中返回旧的数据源。 - Mostafa
显示剩余3条评论
3个回答

27
在调用mDataSource.invalidate()方法后,mDataSource将被无效,并通过DataSource.Factory.create()方法创建新的DataSource实例,因此重要的是在DataSource.Factory.create()方法内每次提供新的DataSource()实例,而不是每次提供相同的DataSource实例。

mDataSource.invalidate()无效,因为在无效之后,CouponListDataSourceFactory提供了相同的已无效的DataSource实例。

修改后,CouponListDataSourceFactory将如下所示,并且调用mCouponListDataSourceFactory.dataSource.invalidate()方法将进行刷新或者,可以在工厂中保留dataSource实例,然后调用LiveData<PagedList<CouponModel>>.getValue().getDataSource().invalidate()方法。

public class CouponListDataSourceFactory extends DataSource.Factory {

private CouponListDataSource dataSource;

private CouponRepository repository;
private String token;
private String vendorId;

public CouponListDataSourceFactory(CouponRepository repository, String token, String vendorId) {
    this.repository = repository;
    this.token = token;
    this.vendorId = vendorId;
}

@Override
public DataSource create() {
    dataSource = new CouponListDataSource(repository, token, vendorId);
    return dataSource;
}
}

1
抱歉,您能否澄清一下您的问题,我无法理解主要思想。不过,这里有一个使用分页库和下拉刷新的工作示例 - Robert Apikyan
我想了解如何在分页库上应用刷新操作,我已经尝试过了,但看起来很丑,当操作开始滑动刷新时,我的适配器为空。 - M. Johnson
好的... 这是您要寻找的行为吗?请在此处检查视频 - Robert Apikyan
问题出在 ModelDataSource::loadInitial 方法中,我不知道为什么,但是在这个方法中 params.requestedStartPosition 的值有时候是 9。所以我只是将 row = params.requestedStartPosition 替换为 row = 0,因为我们总是使用 row = 0 参数进行初始加载。这样就解决了滚动到底部的问题。也许会有更好的解决方案...顺便说一下,我已经推送了修复后的代码,你可以在 ModelDataSource 类中找到更改。 - Robert Apikyan
1
嗨,首先是原因。ModelDataSource.loadInitial()方法已经在后台线程上调用,并且期望在loadInitial方法调用之后数据将被获取。因此,在您的Network类中将caroutine的launch方法替换为runblocking将解决该问题。这是Network类。另一种方法是在loadInitial方法内部同步调用retrofit api方法,而不需要使用多余的caroutin。 - Robert Apikyan
显示剩余8条评论

19
在ViewModel类中添加一个方法。
 public void refresh() {

    itemDataSourceFactory.getItemLiveDataSource().getValue().invalidate();
}

你可以从Activity/Fragment中使用以下内容:

 swipeRefreshLayout.setOnRefreshListener(() -> yourviewModel.refresh());
隐藏下拉刷新布局当recyclerView加载完成。
yourViewModel.itemPagedList.observe(this, allProposalModel -> {


        mAdapter.submitList(model);
        swipeRefreshLayout.setRefreshing(false); //here..


    });

1
调用invalidate后,列表不会再次加载。我需要执行其他操作还是它会自动工作? - Jon
1
在我的情况下,查看日志后,它刷新了所有数据,但没有显示出来。我还应该做什么? - Amg91

1

在新的Paging 3版本中,方法被移动到PagingDataAdapter类中。

val adapter = PagingAdapter(R.layout.item_layout, ::ViewHolder) { i1, i2 -> i1.id == i2.id }

adapter.refresh() // to refresh from the network

adapter.retry() // to retry the current request if the load method returned LoadState.Error()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接