如何将 PagingSource 映射到另一个对象

问题描述 投票:0回答:2

我按照此 Codelab 实现了分页 3。 代码实验室 但是当我创建 UserPagingRepository 时,我遇到数据类不是映射的问题。在 Room DataBase 中,我使用 UserLocal,而我使用 UserRemote 从 api 获取数据。如何将数据从数据层转换到域层(用户类)。

const val NETWORK_PAGE_SIZE = 20

class UserPagingRepository(
    private val service: UserApiService,
    private val database: UserDatabase
) {
    fun getUsersPaging(): Flow<PagingData<User>> {
        val pagingSourceFactory = { database.usersDao().getPagingUsers() }
        return Pager(
            config = PagingConfig(
                pageSize = NETWORK_PAGE_SIZE,
                enablePlaceholders = false
            ),
            pagingSourceFactory = pagingSourceFactory,
            remoteMediator = UserRemoteMediator(service, database)
        )
    }
}

修复:

pager.flow // Type is Flow<PagingData<User>>.
  .map { pagingData ->
    pagingData.map { user -> UiModel(user) }
  }
android kotlin android-jetpack android-paging-3
2个回答
4
投票

在ViewModel中的下游流程中,当您调用分页数据时,在收集之前应用地图。

searchRepo.searchUser(it)
   .map { user ->
      UserData.asDomainLayer()
   }
   .cachedIn(viewModelScope)

0
投票

为了避免表示/UI 层直接依赖于您的数据实体,我编写了一个解决方法来创建直接返回域模型的寻呼机。 以下所有代码都应该位于您的数据层中。

private fun provideMyPager(): Pager<Int, MyModel> {
    return Pager(
        config = PagingConfig(pageSize = Constants.PAGING_PAGE_SIZE),
        remoteMediator = MyRemoteMediator(...).mapped { it.toEntity() },
        pagingSourceFactory = {
            contactsDb.contactsDao.pagingSource().mapped(
                { entity -> entity.toModel() },
                { model -> model.toEntity() },
            )
        }
    )
}



class MyRemoteMediator(
    ...
) : RemoteMediator<Int, MyEntity>() {...}


fun <TEntity : Any, TModel : Any> PagingSource<Int, TEntity>.mapped(
    mapToModel: (TEntity) -> TModel,
    mapToEntity: (TModel) -> TEntity
): PagingSource<Int, TModel> {

    return object : PagingSource<Int, TModel>() {
        private val wrapped = this@mapped

        override fun getRefreshKey(state: PagingState<Int, TModel>): Int? {
            val mappedState = mapPagingState(state, mapToEntity)

            return wrapped.getRefreshKey(mappedState)
        }

        override suspend fun load(params: LoadParams<Int>): LoadResult<Int, TModel> {
            val loadResult = wrapped.load(params)

            val mappedLoadResult = loadResult.run {
                when (this) {
                    is LoadResult.Page -> {

                        LoadResult.Page(
                            data.map(mapToModel),
                            prevKey,
                            nextKey,
                            itemsBefore,
                            itemsAfter
                        )
                    }

                    is LoadResult.Error -> LoadResult.Error(throwable)
                    is LoadResult.Invalid -> LoadResult.Invalid()
                }
            }
            return mappedLoadResult
        }

    }
}

fun <TEntity : Any, TModel : Any> RemoteMediator<Int, TEntity>.mapped(
    mapToEntity: (TModel) -> TEntity
) : RemoteMediator<Int, TModel> {
    return object : RemoteMediator<Int, TModel>() {
        override suspend fun load(
            loadType: LoadType,
            state: PagingState<Int, TModel>
        ): MediatorResult {
            val mappedState = mapPagingState(state, mapToEntity)
            return [email protected](loadType, mappedState)
        }
    }
}


private fun <TModel : Any, TEntity : Any> mapPagingState(
    state: PagingState<Int, TEntity>,
    mapToModel: (TEntity) -> TModel
) : PagingState<Int, TModel> {
    return state.run {
        PagingState(
            pages = pages.map {
                val mappedData = it.data.map(mapToModel)
                PagingSource.LoadResult.Page(
                    mappedData,
                    it.prevKey,
                    it.nextKey,
                    it.itemsBefore,
                    it.itemsAfter
                )
            },
            anchorPosition = anchorPosition,
            config = config,
            leadingPlaceholderCount = 0 // TODO if required, use reflection to find this leadingPlaceHolderCount
        )
    }
© www.soinside.com 2019 - 2024. All rights reserved.