Append data after load in Remote Mediator
まだ誰も着手していません。
評価
- 難易度
- 4/5
- 見積もり時間
- 3〜5日
- 初心者へのやさしさ
- 38/100
調査の方向性
まず、MapPagingSource.load と PokemonApiRemoteMediator.load を通る Pager のフローを追跡し、ログに記録されたシーケンスを adapter に送信された PagingData と比較します。APPEND 中にメモリ内の map がどのように変化するか、また新しく読み込まれたデータを表示可能にするはずのイベントが何かを確認します。関係のない workaround に依存せず、追加された結果が adapter に表示されれば完了です。
索引モデルが issue の本文から書いたものです。
説明
I decided to try Pager without the Room database. I use HashMap as the simplest database.
First I implemented PagingSource.
class MapPagingSource(
private val map: () -> Map<Int, List<Result>>
) : PagingSource<Int, Result>() {
override fun getRefreshKey(state: PagingState<Int, Result>): Int? {
println("TAG PagingSource anchorPosition ${state.anchorPosition}")
val anchor = state.anchorPosition ?: return null
val closest = state.closestPageToPosition(anchor) ?: return null
val page = closest.prevKey?.plus(1) ?: closest.nextKey?.minus(1)
return page
}
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, Result> {
val map = map()
val position = (params.key ?: 0)
println("TAG PagingSource position = $position, size = ${map.size}")
return LoadResult.Page(
data = map[position] ?: emptyList(),
prevKey = if (position == 0) null else position - 1,
nextKey = if (position + 1 < map.size) position + 1 else null
)
}
}
After RemoteMediator
@OptIn(ExperimentalPagingApi::class)
class PokemonApiRemoteMediator(
private val map: () -> MutableMap<Int, List<Result>>,
private val append: () -> Unit
) : RemoteMediator<Int, Result>() {
private val ktor = Ktor()
override suspend fun initialize(): InitializeAction {
println("TAG RemoteMediator initialize")
return InitializeAction.LAUNCH_INITIAL_REFRESH
}
override suspend fun load(loadType: LoadType, state: PagingState<Int, Result>): MediatorResult {
val map = map()
println("TAG RemoteMediator $loadType, ${map.size}")
return try {
val latestPage = when (loadType) {
LoadType.REFRESH -> 0
LoadType.PREPEND -> return MediatorResult.Success(endOfPaginationReached = true)
LoadType.APPEND -> map.size
}
val subList = runCatching {
withContext(Dispatchers.IO) {
ktor.getData(state.config.pageSize, latestPage * state.config.pageSize)
}
}.getOrNull()
val data =
subList?.results ?: return MediatorResult.Success(endOfPaginationReached = true)
if (data.isEmpty()) return MediatorResult.Success(endOfPaginationReached = true)
if (loadType == LoadType.REFRESH) map.clear()
map[latestPage] = data
println("TAG RemoteMediator size ${map.size}")
if (loadType == LoadType.APPEND) append()
MediatorResult.Success(false)
} catch (e: Throwable) {
println("TAG RemoteMediator $e")
MediatorResult.Error(e)
}
}
}
And created a Pager in ViewModel
private val data: MutableMap<Int, List<Result>> = HashMap()
private var latestSource: MapPagingSource? = null
@OptIn(ExperimentalPagingApi::class)
private val _pager = Pager(
config = PagingConfig(10, enablePlaceholders = false),
remoteMediator = PokemonApiRemoteMediator(map = { data }) { },
pagingSourceFactory = {
println("TAG create source")
MapPagingSource { data }.also {
latestSource = it
} }
val adapter = Adapter()
init {
_pager.flow
.onEach {
println("TAG PagingData $it")
adapter.submitData(it)
}.launchIn(viewModelScope)
}
As I can see, the PagingData was created and sent to the adapter.
Then the PagingSource did not find the data and started the RemoteMediator.
After loading, the work stopped and the PagingSource did not start loading the data.
Of course, I can call "invalidate". But this will recreate the PagingSource, and will not add the data as if it were just making requests to the network from the PagingSource.
- 主要言語
- Kotlin
- スター
- 509
- フォーク
- 268
- PR マージ指標
- 30日以内にマージされた PR はありません
環境構築
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
android/codelab-android-paging のほかの issue
-
難易度 1/5 1時間未満 初心者へのやさしさ 62/100
android/codelab-android-paging#236 · リアクション 3 件 ·
-
難易度 3/5 1〜2日 初心者へのやさしさ 35/100
-
難易度 2/5 1〜3時間 初心者へのやさしさ 35/100
android/codelab-android-paging#243 · コメント 1 件 · リアクション 1 件 ·
-
難易度 2/5 1〜2日 初心者へのやさしさ 35/100
android/codelab-android-paging#241 · コメント 1 件 ·
-
難易度 3/5 1〜2日 初心者へのやさしさ 15/100
android/codelab-android-paging の issue をすべて見る
似ている issue
-
難易度 1/5 1時間未満 初心者へのやさしさ 95/100
-
難易度 2/5 1〜3時間 初心者へのやさしさ 74/100
T31n/YagniLauncher#1051 ·
メンテナーはふだん 1 日以内に返信
-
Accepted Needs Triage
難易度 2/5 1〜3時間 初心者へのやさしさ 84/100
ankidroid/Anki-Android#22114 · コメント 5 件 · 担当者 1 名 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
solana-foundation/pay-kit#341 ·
メンテナーはふだん 1 日以内に返信