干净的架构:无法将 PagingSource<Int, Entities> 映射到 PagingSource<RepositoryModel>

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

我的要求是使用干净的架构以及离线支持在页面中显示注释。 我正在使用 Paging 库进行分页。下面是用于获取笔记的清晰架构图。

enter image description here

注意:请在新选项卡中打开上图并缩放以清晰查看。

我有四层UIUseCaseRepositoryDatasource。我打算抽象数据源的内部实现。为此,我需要在跨越边界之前将

NotesEntities
映射到另一个模型。

class TimelineDao{
    @Transaction
    @Query("SELECT * FROM NotesEntities ORDER BY timeStamp DESC")
    abstract fun getPagingSourceForNotes(): PagingSource<Int, NotesEntities>
}

当前实施:

internal class NotesLocalDataSourceImpl @Inject constructor(
    private val notesDao: NotesDao
) : NotesLocalDataSource {
    override suspend fun insertNotes(notes: NotesEntities) {
        notesDao.insert(NotesEntities)
    }

    override fun getNotesPagingSource(): PagingSource<Int, NotesEntities> {
        return notesDao.getPagingSourceForNotes()
    }
}

预期实施:

internal class NotesLocalDataSourceImpl @Inject constructor(
    private val notesDao: NotesDao
) : NotesLocalDataSource {
    override suspend fun insertNotes(notes: NotesRepositoryModel) {
        notesDao.insert(NotesRepositoryModel.toEntity())
    }

    override fun getNotesPagingSource(): PagingSource<Int, NotesRepositoryModel> {
        return notesDao.getPagingSourceForNotes().map{ it.toNotesRepositoryModel() }
    }
}

我在将

PagingSource<Int, NotesEntities>
映射到
PagingSource<Int, NotesRespositoryModel>
时遇到问题。据我研究,没有办法映射
PagingSource<Int, NotesEntities>
PagingSource<Int, NotesRespositoryModel>

请告诉我是否有一种干净的方法/解决方法来映射分页源对象。如果有人确定现在没有办法的话。也请留下评论。

请注意:我知道分页允许对

PagingData
进行转换。下面是在页面中获取注释的代码片段。它将
NotesEntities
映射到
NotesDomainModel
。但后来我想在
NotesRespositoryModel
中使用
NotesEntities
而不是
NotesRespositoryImpl
,抽象出
NotesEntities
层中的
NotesLocalDataSourceImpl 

override fun getPaginatedNotes(): Flow<PagingData<NotesDomainModel>> {
     return Pager<Int, NotesEntities>(
               config = PagingConfig(pageSize = 10),
               remoteMediator = NotesRemoteMediator(localDataSource,remoteDataSource),
               pagingSourceFactory = localDataSource.getNotesPagingSource()
           ).flow.map{ it.toDomainModel() }
}

我想到的解决方案:

我没有直接在 Dao 中使用

PagingSource
,而是想创建一个自定义 PagingSource,它调用 Dao 并将
NoteEntities
映射到
LocalRepositoryModel

但是我需要明白,对数据库的任何更新都不会反映在

PagingSource
中。我需要在内部处理它。

请告诉我您对此的想法。

pagination android-room clean-architecture android-paging android-paging-3
1个回答
0
投票

创建一个

PagingSource
的实现,将所有调用转发到原始
PagingSource
并执行映射,如下所示:

class MappingPagingSource<Key: Any, Value: Any, MappedValue: Any>(
  private val originalSource: PagingSource<Key, Value>,
  private val mapper: (Value) -> MappedValue,
) : PagingSource<Key, MappedValue>() {
  
  override fun getRefreshKey(state: PagingState<Key, MappedValue>): Key? {
    return originalSource.getRefreshKey(
      PagingState(
        pages = emptyList(),
        leadingPlaceholderCount = 0,
        anchorPosition = state.anchorPosition,
        config = state.config,
      )
    )
  }

  override suspend fun load(params: LoadParams<Key>): LoadResult<Key, MappedValue> {
    val originalResult = originalSource.load(params)
    return when (originalResult) {
      is LoadResult.Error -> LoadResult.Error(originalResult.throwable)
      is LoadResult.Invalid -> LoadResult.Invalid()
      is LoadResult.Page -> LoadResult.Page(
        data = originalResult.data.map(mapper),
        prevKey = originalResult.prevKey,
        nextKey = originalResult.nextKey,
      )
    }
  }

  override val jumpingSupported: Boolean
    get() = originalSource.jumpingSupported
}

那么用法会是这样的:

override fun getNotesPagingSource(): PagingSource<Int, NotesRepositoryModel> {
  return MappingPagingSource(
    originalSource = notesDao.getPagingSourceForNotes(),
    mapper = { it.toNotesRepositoryModel() },
  )
}

关于

pages
中的空
PagingState
- 将所有加载的页面映射回原始值会太昂贵,并且房间的分页实现仅使用
anchorPosition
config.initialLoadSize
- 请参阅 herehere

© www.soinside.com 2019 - 2024. All rights reserved.