Sort array items when using PagedListAdapter?
Asked Answered
S

3

7

I'm using the Paging library.

Currently, I want to sort (using SortList) the items by the description in PagedListAdapter but I have not figured out how to do it.

How to sort elements when using a PagedListAdapter? Thank you.

Sollows answered 13/7, 2018 at 8:29 Comment(2)
same question here!Washko
Are you able to sort the paged list?Herminahermine
I
7

I faced this problem too, and was surprised that PagedList doesn't seem to have a straightforward way to sort items. Here's how I achieved the effect I needed using DataSource's mapByPage():

/** sorts MyItems by timestamp in descending order */
private fun DataSource.Factory<Long, MyItem>.sortByDescTime(): DataSource.Factory<Long, MyItem> {
return mapByPage {
    myItemsList.sortedWith(compareByDescending { item -> item.timeStamp })
  }
}

i.e, the input of mapByPage() should be your sorting function (depends on your setup, mine uses the Kotlin extensions & lambda syntax to sort the items in the target list - using Collections.sortedWith())

And then, used my extension function on the data source to sort the fetched items:

fun fetchItems(userId: Long): LiveData<PagedList<MyItem>> {
    val itemDataSource = itemAPIService.getItems(userId).sortByDescTime()
    val itemPagedList = LivePagedListBuilder(itemDataSource, 10).build()
    return itemPagedList
}
Ion answered 20/6, 2019 at 13:18 Comment(1)
Too bad there isn't a build in implementation of this one, anyway - great job. Works perfectly.Signorino
F
1

you need to use MediatorLiveData here. though below code is in java, it should serve the basic purpose. In Your ViewModel add both

public LiveData<PagedList<Customer>> customerList;
public MediatorLiveData<PagedList<Customer>> customerListMediator;

then first fetch liveData, that is, customerList in my case

customerList = new LivePagedListBuilder<>(mAppRepository.getCustomers(new SimpleSQLiteQuery(dynamicQuery)),1).build();

after that use the mediatorLiveData:-

customerListMediator.addSource(customerList, new Observer<PagedList<Customer>>() {
        @Override
        public void onChanged(@Nullable PagedList<Customer> customers) {
            customerListMediator.setValue(customers);
        }
    });

And in your recyclerview, don't use LiveData list, instead use mediatorLiveData, in my case customerListMediator. like below:-

mViewModel.customerListMediator.observe(this, customers -> {
        mViewModel.customerListAdapter.submitList(customers);
        Toast.makeText(this, "list updated.", Toast.LENGTH_SHORT).show();
    });
Feints answered 19/9, 2020 at 4:42 Comment(0)
T
1

mapByPage() function works, but has side effects as you would need to "prepend" the next page items in the PagedList to have the desired effect.

Using Room @Dao and SQL sorting capabilities you can do something like this, which seems more performant as it releases sorting operations from the UI components:

@Dao
public interface MyItemDao{

    enum SORT_OPT {
        LABEL_ASC, LABEL_DESC, PRICE_ASC, PRICE_DESC, RATING_ASC, RATING_DESC
    }

    @Update
    void update(ItemEntity itemEntity);

    @Delete
    void delete(ItemEntity itemEntity);

    @Query("DELETE FROM item_table")
    void deleteAll();

    @Query("SELECT * FROM item_table ORDER BY price ASC")
    @Transaction
    DataSource.Factory<Integer, ItemEntity> getProductsOrderByPriceAsc();

    @Query("SELECT * FROM item_table ORDER BY price DESC")
    @Transaction
    DataSource.Factory<Integer, ItemEntity> getProductsOrderByPriceDesc();


    @Query("SELECT * FROM item_table ORDER BY label ASC")
    @Transaction
    DataSource.Factory<Integer, ItemEntity> getProductsOrderByLabelAsc();


    @Query("SELECT * FROM item_table ORDER BY label DESC")
    @Transaction
    DataSource.Factory<Integer, ItemEntity> getProductsOrderByLabelDesc();


    @Query("SELECT * FROM product_table ORDER BY totalRating ASC")
    @Transaction
    DataSource.Factory<Integer, ItemEntity> getProductsOrderByRatingAsc();


    @Query("SELECT * FROM product_table ORDER BY totalRating DESC")
    @Transaction
    DataSource.Factory<Integer, ItemEntity> getProductsOrderByRatingDesc();


    default DataSource.Factory<Integer, ItemEntity> getSortedProducts(SORT_OPT sortOptions) {

        switch (sortOptions) {
            case LABEL_ASC:
                return getProductsOrderByLabelAsc();
            case LABEL_DESC:
                return getProductsOrderByLabelDesc();
            case PRICE_ASC:
                return getProductsOrderByPriceAsc();
            case PRICE_DESC:
                return getProductsOrderByPriceDesc();
            case RATING_ASC:
                return getProductsOrderByRatingAsc();
            case RATING_DESC:
                return getProductsOrderByRatingDesc();
            default:
                return null;
        }
    }

As you can notice the most important method here is: default DataSource.Factory<Integer, ItemEntity> getSortedProducts(SORT_OPT sortOptions)

You can store you sort value in sharedPreferences and load it from there.

Tomfool answered 22/2, 2021 at 12:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.