RemoteMediator PREPEND is getting called multiple times when not needed
Nadie ha tomado este issue todavía.
Evaluación
- Dificultad
- 4/5
- Tiempo estimado
- 3-5 días
- Aptitud para principiantes
- 25/100
Línea de trabajo
Comienza con el PagingWithNetworkSample modificado e inspecciona PageKeyedRemoteMediator.load, la configuración de Pager en postsOfSubreddit y RedditPostDao.postsBySubreddit. Reproduce la secuencia REFRESH, PREPEND y APPEND con las versiones indicadas de Paging, Room y Kotlin; después, sigue el motivo por el que se repiten las cargas de límite y define el número esperado de requests antes de cambiar el comportamiento.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
I'm facing an issue with paging library requesting 'too much' data when requesting the information from the middle of the 'data source':
For my scenario I can request both previous and next pages (Remote mediator load types PREPEND and APPEND). After initial portion (Remote mediator loadType REFRESH) and one APPEND and one PREPEND (as far as I can see from the source code paging lib will always request one page before and one page after after initial REFRESH) the library call mediator's load with 'PREPEND' loadType 1-3 more times, doesn't matter how big my page (and initial load) is, 30 or 300 elements. So my network calls sequence looks like
---> REFRESH
---> PREPEND
---> APPEND
---> PREPEND
---> PREPEND
When I'm scrolling and reaching boundary conditions, paging lib often requests 2-3 pages, instead of 1.
This all happens only when both PREVIOUS and NEXT pages are available. If user can scroll one direction only, most of the time, only 1 page is requested when user hits boundary condition.
Is it possible to control how many pages does paging library request (in order to reduce payload on the backend)
For the testing purposes, I modified this sample app to get 'endless stream of network data': https://github.com/android/architecture-components-samples/tree/master/PagingWithNetworkSample
@OptIn(ExperimentalPagingApi::class)
class PageKeyedRemoteMediator(
private val db: RedditDb,
private val redditApi: RedditApi,
private val subredditName: String
) : RemoteMediator<Int, RedditPost>() {
private val postDao: RedditPostDao = db.posts()
private val remoteKeyDao: SubredditRemoteKeyDao = db.remoteKeys()
var minIndex = 0
var maxIndex = 0
override suspend fun initialize(): InitializeAction {
// Require that remote REFRESH is launched on initial load and succeeds before launching
// remote PREPEND / APPEND.
return InitializeAction.LAUNCH_INITIAL_REFRESH
}
override suspend fun load(
loadType: LoadType,
state: PagingState<Int, RedditPost>
): MediatorResult {
try {
delay(1000)
val size = if (loadType == REFRESH) state.config.initialLoadSize else state.config.pageSize
println(">>>>> $loadType: ${if (loadType == APPEND) minIndex else maxIndex}")
val items = (0 until size).map {
val value = if (loadType == APPEND) minIndex-- else maxIndex++
RedditPost(
name = value.toString(),
title = value.toString(),
score = value,
author = value.toString(),
subreddit = subredditName,
num_comments = value,
created = System.currentTimeMillis(),
thumbnail = null,
url = null
).apply {
indexInResponse = value
}
}
db.withTransaction {
if (loadType == REFRESH) {
postDao.deleteBySubreddit(subredditName)
}
postDao.insertAll(items)
}
return MediatorResult.Success(endOfPaginationReached = items.isEmpty())
} catch (e: IOException) {
return MediatorResult.Error(e)
} catch (e: HttpException) {
return MediatorResult.Error(e)
}
}
}
@Dao
interface RedditPostDao {
...
@Query("SELECT * FROM posts WHERE subreddit = :subreddit ORDER BY num_comments DESC")
fun postsBySubreddit(subreddit: String): PagingSource<Int, RedditPost>
...
}
...
override fun postsOfSubreddit(subReddit: String, pageSize: Int) = Pager(
config = PagingConfig(pageSize),
remoteMediator = PageKeyedRemoteMediator(db, redditApi, subReddit)
) {
db.posts().postsBySubreddit(subReddit)
}.flow
...
@OptIn(ExperimentalCoroutinesApi::class, FlowPreview::class)
val posts = flowOf(
clearListCh.receiveAsFlow().map { PagingData.empty<RedditPost>() },
savedStateHandle.getLiveData<String>(KEY_SUBREDDIT)
.asFlow()
.flatMapLatest { repository.postsOfSubreddit(it, 100) }
// cachedIn() shares the paging state across multiple consumers of posts,
// e.g. different generations of UI across rotation config change
.cachedIn(viewModelScope)
).flattenMerge(2)
...
lifecycleScope.launchWhenCreated {
model.posts.collectLatest {
adapter.submitData(it)
}
}
Paging infra setup:
- Local db + Network (RemoteMediator)
- Room at persistence layer
- Coroutines
- Libs versions:
- paging = "3.1.0-rc01"
- room = "2.4.0-beta01"
- kotlin = "1.4.21"
- recyclerview = "1.2.1"
- Lenguaje dominante
- Kotlin
- Estrellas
- 509
- Forks
- 268
- Métricas de merge de PR
- Sin PR fusionados en 30 d
Preparar el entorno
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de android/codelab-android-paging
-
Dificultad 1/5 Menos de una hora Aptitud para principiantes 62/100
android/codelab-android-paging#236 · 3 reacciones ·
-
Dificultad 3/5 1-2 días Aptitud para principiantes 35/100
-
Dificultad 4/5 3-5 días Aptitud para principiantes 38/100
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 35/100
android/codelab-android-paging#243 · 1 comentario · 1 reacción ·
-
Dificultad 2/5 1-2 días Aptitud para principiantes 35/100
android/codelab-android-paging#241 · 1 comentario ·
Todos los issues de android/codelab-android-paging
Issues similares
-
Dificultad 1/5 Menos de una hora Aptitud para principiantes 95/100
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 74/100
T31n/YagniLauncher#1051 ·
Los mantenedores suelen responder en 1 día
-
Accepted Needs Triage
Dificultad 2/5 1-3 horas Aptitud para principiantes 84/100
ankidroid/Anki-Android#22114 · 5 comentarios ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
solana-foundation/pay-kit#341 ·
Los mantenedores suelen responder en 1 día