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.

landerlyoung
  • 1,693
  • 17
  • 14
  • 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) – Marco Pierucci May 27 '18 at 01:13

1 Answers1

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(this@PetViewModel.genderMutableData) { 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?) {
    this@PetViewModel.genderMutableData.postValue("female")
}

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

dphans
  • 1,543
  • 19
  • 20
  • what about add a new Pet? How to trigger PagedListAdapter update with that new Pet? – Slim_user71169 Nov 03 '18 at 06:21
  • 1
    @Slim_user71169 this based on your return type of Dao methods. For `LiveData`, `Datasource.Factory`,... Datasource will trigger changes automatically when models updates. – dphans Apr 01 '19 at 08:32
  • 2
    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> in ViewModel. Is there any example like that? – james04 Jan 25 '20 at 10:42
  • 3
    This is not transformation! What OP asking is that, instead of passing `PagedList` to `PagedListAdapter` via `submitList`, he needs a method to transform `Pet` to `TransformedPet`, so that he can pass `PagedList` to `PagedListAdapter` via `submitList`. Now, the million dollar question is, how do you get `PagedList`, because your Dao is returning `DataSource.Factory` ? – Cheok Yan Cheng May 31 '20 at 16:23
  • @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. – aminography Jun 05 '20 at 11:42
  • 2
    Do anyone know to transform PagedList to PagedList – Ferer Atlus Jul 13 '20 at 14:27