Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implement SwipeRefreshLayout with the new Paging Library

I got an activity that shows a list of items to the user and it uses the Paging Library. My problem is that I can't reload the list when user swipes down the screen so that it fetches data from the server again.

Here is my DataSource Factory:

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;
    }
}

And here's how I create the PagedList

PagedList.Config config = new PagedList.Config.Builder()
                .setInitialLoadSizeHint(15)
                .setPageSize(10)
                .build();
LiveData<PagedList<Coupon>> couponsLiveData = new LivePagedListBuilder<>(dataSourceFactory, config).build();
like image 555
Mostafa Avatar asked Apr 28 '18 09:04

Mostafa


People also ask

How do you use SwipeRefreshLayout?

Add the SwipeRefreshLayout Widget To add the swipe to refresh widget to an existing app, add SwipeRefreshLayout as the parent of a single ListView or GridView . Remember that SwipeRefreshLayout only supports a single ListView or GridView child. You can also use the SwipeRefreshLayout widget with a ListFragment .

What is paging library?

The Paging Library lets you load data directly from your backend using keys that the network provides. Your data can be uncountably large. Using the Paging Library, you can load data into pages until there isn't any data remaining. You can observe your data more easily.

How do I stop swipe refresh layout?

To disable the gesture and progress animation, call setEnabled(false) on the view. This layout should be made the parent of the view that will be refreshed as a result of the gesture and can only support one direct child.


2 Answers

After calling the mDataSource.invalidate() method, mDataSource will be invalidated and the new DataSource instance will be created via DataSource.Factory.create() method, so its important to provide new DataSource() instance every time inside DataSource.Factory.create() method, do not provide same DataSource instance every time.

mDataSource.invalidate() is not working, because after invalidation, CouponListDataSourceFactory provides the same, already invalidated DataSource instance.

After modification CouponListDataSourceFactory will be looked like in below smple, and call to mCouponListDataSourceFactory.dataSource.invalidate() method will make a refresh, alternatively instead of keeping dataSource instance inside the factory, we can call invalidate method on 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;
}
}
like image 189
Robert Apikyan Avatar answered Nov 03 '22 23:11

Robert Apikyan


Add a method in ViewModel class

 public void refresh() {

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

and from the Activity/Fragment you can use

 swipeRefreshLayout.setOnRefreshListener(() -> yourviewModel.refresh());

Hide the refresh layout when the reyclerView gets loaded

yourViewModel.itemPagedList.observe(this, allProposalModel -> {


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


    });
like image 31
Jiten Basnet Avatar answered Nov 03 '22 23:11

Jiten Basnet