Petite question :
Quelle est la bonne façon de gérer la base de données + réseau sur la bibliothèque de pagination à partir de composants Architecture, en utilisant une API qui utilise page + taille pour charger une nouvelle page et la classe BoundaryCallback
?
Recherche et explication
Actuellement, la classe BoundaryCallback
utilisée dans la bibliothèque de pagination pour les composants d'architecture, reçoit en paramètre l'instance d'un élément de la liste sans contexte réel de l'emplacement de cet élément. Cela se produit dans onItemAtFrontLoaded
et onItemAtEndLoaded
.
Mon Api est censé recevoir la page et la taille de la page pour charger le bloc de données suivant. Le rappel de limite, ajouté en tant que composant du générateur de liste paginée, est censé vous indiquer quand charger la page suivante de données en fonction de la distance de prélecture et de la taille de la page.
Étant donné que l'API a besoin du numéro de page et de la taille de la page, je ne vois pas comment l'envoyer à l'API simplement en recevant l'un des éléments de la liste proposé dans onItemAtFrontLoaded
et onItemAtEndLoaded
. En vérifiant les exemples de Google dans ce lien , ils utilisent le nom du dernier élément pour obtenir le suivant, mais cela ne correspond pas à un Api avec page + taille.
Ils ont aussi un autre exemple avec uniquement un réseau qui utilise PagedKeyedDatasource
, mais il n’ya pas d’échantillon ni d’indication sur la façon de le mélanger à la base de données et au BoundaryCallback.
Modifier : Seules les solutions que j'ai trouvées jusqu'à présent consistent à stocker la dernière page chargée dans les préférences partagées, mais cela peut sembler être un sale tour.
Reportez-vous à https://github.com/googlesamples/Android-architecture-components/issues/252#issuecomment-392119468 pour obtenir des commentaires officiels à ce sujet.
J'implémente ceci:
PagedList.BoundaryCallback<Produto> boundaryCallbackNovidades = new PagedList.BoundaryCallback<Produto>(){
int proxPagina;
boolean jaAtualizouInicio=false;
public void onZeroItemsLoaded() {
requestProdutos(
webService.pesquisarNovidadesDepoisDe(LocalDateTime.now().format(Util.formatterDataTime), 0, 20));
}
public void onItemAtFrontLoaded(@NonNull Produto itemAtFront) {
if(!jaAtualizouInicio)
requestProdutos(
webService.pesquisarNovidadesMaisRecentesQue(itemAtFront.data.format(Util.formatterDataTime)));
jaAtualizouInicio=true;
}
public void onItemAtEndLoaded(@NonNull Produto itemAtEnd) {
requestProdutos(
webService.pesquisarNovidadesDepoisDe(LocalDateTime.now().format(Util.formatterDataTime), proxPagina++, 20));
}
};
public LiveData<PagedList<Produto>> getNovidades(){
if(novidades==null){
novidades = new LivePagedListBuilder<>(produtoDao.produtosNovidades(),
10)
.setBoundaryCallback(boundaryCallbackNovidades)
.build();
}
return novidades;
}
Disons que vous récupérez toujours les objets N=10
Par page sur le serveur, puis les stockez dans la base de données. Vous pouvez obtenir le nombre d'éléments dans la base de données en utilisant la requête SQL SELECT COUNT(*) FROM tbl
& stockez-la dans la variable count
. Maintenant, pour obtenir le numéro de page qui devrait être demandé ensuite, utilisez:
val nextPage: Int = (count / N) + 1
La documentation a ceci à dire sur le sujet:
Si vous n'utilisez pas d'API réseau à clé d'élément, vous utilisez peut-être une clé de page ou une page d'index. Si tel est le cas, la bibliothèque de pagination ne connaît pas la clé de page ou l'index utilisé dans BoundaryCallback, vous devez donc effectuer le suivi vous-même. Vous pouvez le faire de deux manières:
Touche de page de stockage local
Si vous souhaitez reprendre parfaitement votre requête, même si l'application est supprimée et reprise, vous pouvez stocker la clé sur le disque. Notez qu'avec une API de réseau index de position/page, il existe un moyen simple de le faire, en utilisant listSize en tant qu'entrée pour le prochain chargement (ou listSize/NETWORK_PAGE_SIZE, pour l'indexation de page). La taille de la liste actuelle n'est pas transmise au BoundaryCallback. En effet, PagedList ne connaît pas nécessairement le nombre d'éléments stockés dans le stockage local. Les espaces réservés peuvent être désactivés ou la source de données peut ne pas compter le nombre total d'éléments.
Au lieu de cela, pour ces cas de positionnement, vous pouvez interroger la base de données pour connaître le nombre d'éléments et le transmettre au réseau.
Touche de page en mémoire
Souvent, il n’est pas judicieux d’interroger la page suivante du réseau si la dernière page que vous avez récupérée a été chargée plusieurs heures ou plusieurs jours auparavant. Si vous conservez la clé en mémoire, vous pouvez actualiser à tout moment la pagination depuis une source réseau. Stockez la clé suivante en mémoire, dans votre BoundaryCallback. Lorsque vous créez un nouveau BoundaryCallback lors de la création d'un nouveau LiveData/Observable of PagedList, actualisez les données. Par exemple, dans Paging Codelab, l’index de page réseau GitHub est stocké en mémoire.
Et des liens vers un exemple de Codelab: https://codelabs.developers.google.com/codelabs/Android-paging/index.html#8