I am using clean architecture with paging 3 and trying to populate a lazyColumn.
I have the following class in my data layer module and I don't want to pass the PagingData to the domain layer as I want to keep the domain free of any Android SDK.
class RepositoryImp @Inject constructor(
private val foodService: FoodService,
private val foodDatabase: FoodDatabase) : Repository {
@OptIn(ExperimentalPagingApi::class)
override fun fetchAllComplexSearch(): Flow<ResponseState<List<ComplexSearchEntity>>> {
val pagingSourceFactory = { foodDatabase.foodDao().fetchAllComplexSearchPaging() }
val pagingDataResult = Pager(
config = PagingConfig(pageSize = ITEMS_PER_PAGE_DEFAULT),
remoteMediator = ComplexSearchRemoteMediator(
foodDatabase = foodDatabase, foodService = foodService
),
pagingSourceFactory = pagingSourceFactory
).flow
val data = pagingDataResult.map { pagingData ->
pagingData.map { complexSearchModel ->
ResponseState.Success(
listOf(
ComplexSearchEntity(
complexSearchModel.id,
complexSearchModel.title,
complexSearchModel.image,
complexSearchModel.imageType
)
)
)
}
}
return data
}
I want to return this Flow<ResponseState<List<ComplexSearchEntity>>>
But I get the following error:
Type mismatch.
Required:
Flow<ResponseState<List<ComplexSearchEntity>>>
Found:
Flow<PagingData<ResponseState.Success<List<ComplexSearchEntity>>>>
It seems like I am wrapping the ResponseState.Success(...) inside the PagingData
Then the presentation layer module will map the Response.Success in a PagingData to be used as a LazyPagingItems<ComplexSearchEntity>
in a LazyColumn.
To achieve the desired functionality, your repository should expose a PagingData<ComplexSearchEntity>
rather than a ResponseState<List<ComplexSearchEntity>>
. This adjustment allows for a cleaner architecture by keeping paging logic within the repository layer and not spreading data layer objects to other layers, thus maintaining a clear separation of concerns.
For your domain model to support this, you can include the following dependency, which is pure Kotlin compatible and allows a repository or use case to expose PagingData
:
implementation("androidx.paging:paging-common:3.2.1")
Then, within your repository implementation, you should move the logic for creating the Pager
from the UI or ViewModel layer to the repository itself. Here's how you could implement this:
@OptIn(ExperimentalPagingApi::class)
override fun fetchAllComplexSearch(): Flow<PagingData<ComplexSearchEntity>> {
val pagingSourceFactory = { foodDatabase.foodDao().fetchAllComplexSearchPaging() }
return Pager(
config = PagingConfig(pageSize = ITEMS_PER_PAGE_DEFAULT),
remoteMediator = ComplexSearchRemoteMediator(
foodDatabase = foodDatabase, foodService = foodService
),
pagingSourceFactory = pagingSourceFactory
).flow
}