How to transform items in a PagedList?(Android Arch Component Paging Library)
Asked Answered
A

1

22

Android Architecture Component now introduced Paging Library, which is great.

According to the official demo The DataSource.Factory now supports map and mapByPage methods, which means we may transform items in one DataSource.

But DataSource and DataSource.Factory should be in the model layer, not the Presentor/View layer. However, there are plenty of times when we want to transform data in our Adapter(for RecyclerView or ListView), and obviously, this is the Presentor/View layer logic. By now, an Adapter holds an instance of PagedList, but PageList can't support these operations, which is kinda awkward. Besides, there are still times when we want to add items or remove items to/from a PagedList.

So this is a feature request:

  1. Support item transformations on a PagedList

  2. Support item adding/removing to/from a PagedList

Any discussion is welcomed.

Anatropous answered 27/4, 2018 at 8:57 Comment(1)
I think the Domain model is not the main issue, you can treat just the PagedList as a domain class and abstract the factory and datasoruce in the data layer. The issue I see is when you need to make transformation in the presentation layer. (assuming arch layers as data-domain-presentation)Methadone
C
3

I think you need use transformations for PagedList instead of LiveData<List<YourModel>>.

For example, I have a list of Pet, each Pet have gender. I need to show paging of Pet and filter gender in runtime.

So, my Dao interface may be:

@Dao
inteface PetDao {
    @Query("SELECT * FROM Pet WHERE Pet.gender = :gender ORDER BY Pet.id ASC")
    fun getPetsByGenderDataFactory(gender: String?): Datasource.Factory<Int, Pet>
}

In ViewModel class, I will use Transformations to filter LiveData<PagedList<Pet>> instead of LiveData<List<Pet>>:

class PetViewModel {

    private val genderMutableData: MutableLiveData<String> = MutableLiveData()
    private val petItemsData: LiveData<PagedList<Pet>> = Transformations.switchMap([email protected]) { petGender ->
        LivePagedListBuilder(AppDatabase.getDefault().getPetDao().getPetsByGenderDataFactory(petGender), 20).build()
    }

}

When user change gender of Pet, you just update value of genderMutableData, it will trigger data source for petItemsData and update Pet items:

fun updatePetItemsWithNewGender(gender: String?) {
    [email protected]("female")
}

Sorry, I'm using Kotlin for example because you don't flag post in Java language.

Chambray answered 27/10, 2018 at 10:12 Comment(6)
what about add a new Pet? How to trigger PagedListAdapter update with that new Pet?Parthenopaeus
@Parthenopaeus this based on your return type of Dao methods. For LiveData, Datasource.Factory<Int, Model>,... Datasource will trigger changes automatically when models updates.Chambray
I dont think that what you are doing above is a Tranformation. The main point is to pull a PagedList of Model_A from database and transform it to LiveData<List<Model_b>> in ViewModel. Is there any example like that?Mendy
This is not transformation! What OP asking is that, instead of passing PagedList<Pet> to PagedListAdapter via submitList, he needs a method to transform Pet to TransformedPet, so that he can pass PagedList<TransformedPet> to PagedListAdapter via submitList. Now, the million dollar question is, how do you get PagedList<TransformedPet>, because your Dao is returning DataSource.Factory<Integer, Pet> ?Chat
@CheokYanCheng: I explored the source code of paging library before and found that unfortunately there is no way to transform data type unless this functionality gets added to the PagedList by owners.Toothed
Do anyone know to transform PagedList<CustomEntity> to PagedList<CustomModel>Metatarsal

© 2022 - 2024 — McMap. All rights reserved.