J'utilise la bibliothèque de pagination pour paginer une liste d'éléments que je récupère de mon serveur. Initialement, lorsque mon fragment est chargé, il renvoie une liste vide. Mais après avoir changé des fragments et revenir à ce fragment, je peux voir la liste chargée. Après le débogage, j'ai vu que les données étaient en train d'être récupérées, mais une liste vide a été transmise à mon fragment.
ItemDataSource:
@Override
public void loadInitial(@NonNull LoadInitialParams<Integer> params, @NonNull LoadInitialCallback<Integer, Item> callback) {
apiService.getItems(OFFSET)
.enqueue(new Callback<ItemWrapper>() {
@Override
public void onResponse(@NonNull Call<ItemWrapper> call,@NonNull Response<ItemWrapper> response) {
callback.onResult(response.body().getItems(), null, OFFSET + 25);
}
@Override
public void onFailure(@NonNull Call<ItemWrapper> call,@NonNull Throwable t) {
t.printStackTrace();
}
});
}
@Override
public void loadBefore(@NonNull LoadParams<Integer> params, @NonNull LoadCallback<Integer, Item> callback) {
}
@Override
public void loadAfter(@NonNull LoadParams<Integer> params, @NonNull LoadCallback<Integer, Item> callback) {
apiService.getItems(params.key)
.enqueue(new Callback<ItemWrapper>() {
@Override
public void onResponse(@NonNull Call<ItemWrapper> call,@NonNull Response<ItemWrapper> response) {
Integer key = response.body().getItems().isEmpty() ? null : params.key + 25;
callback.onResult(response.body().getItems(), key);
}
@Override
public void onFailure(@NonNull Call<ItemWrapper> call,@NonNull Throwable t) {
t.printStackTrace();
}
});
}
ItemDataSourceFactory:
@Override
public DataSource create() {
ItemDataSource itemDataSource = new ItemDataSource();
itemLiveDataSource.postValue(itemDataSource);
return itemDataSource;
}
public MutableLiveData<ItemDataSource> getItemLiveDataSource() {
return itemLiveDataSource;
}
ItemViewModel:
private LiveData<ItemDataSource> liveDataSource;
private LiveData<PagedList<Item>> itemPagedList;
private ItemViewModel(Application application) {
ItemDataSourceFactory factory = new ItemDataSourceFactory();
liveDataSource = factory.getItemLiveDataSource();
PagedList.Config config = (new PagedList.Config.Builder())
.setEnablePlaceholders(false)
.setPageSize(ItemDataSource.LIMIT).build();
itemPagedList = (new LivePagedListBuilder(factory, config)).build();
}
public LiveData<PagedList<Item>> getItems() {
return itemPagedList;
}
Fragment:
ItemViewModel itemViewModel = ViewModelProviders.of(this).get(ItemViewModel.class);
itemViewModel.getItems.observe(this, items -> {
adapter.submitList(items);
})
Pas sûr à 100%, mais je pense que c'est parce que vous exécutez une demande asynchrone. essayez de le changer pour qu'il fonctionne de manière synchrone pour loadInitial()
comme ça request.execute()
J'ai également eu ce problème une fois et je n'arrive toujours pas à comprendre pourquoi cela ne fonctionne pas pour certains fragments. La solution que j'ai trouvée, qui ressemble plus à une solution rapide et sommaire, consiste à charger le fragment deux fois.
Yassin Ajdi a raison. loadinitial()
appelle immédiatement sur le même thread sur lequel PagedList est créé. Comme votre API est asynchrone, la méthode s'exécute vide pour la première fois
Si, comme moi, quelqu'un utilise un appel asynchrone RxJava/Kotlin dans loadInitial
. J'ai finalement trouvé une solution après de nombreuses heures douloureuses.
J'ai essayé d'utiliser un gestionnaire retardé (500 ms) dans la méthode Observer
mais il était inconstant et ne fonctionnait pas dans tous les scénarios. Peu importe combien j'ai essayé de le rendre synchrone en utilisant setFetcher
et Rx observeOn
, cela ne fonctionnerait pas de manière cohérente.
Ma solution était d'utiliser .blockingSubscribe
dans mon Observable. Mon récupérateur de données utilisait une bibliothèque Socket qui avait sa propre concurrence hors de ma portée, donc je ne pouvais pas garantir que je pouvais rendre le processus entièrement synchrone comme l'exige la pagination. (Un processus qui nécessite une meilleure documentation OMI). Quoi qu'il en soit, voici ma solution, j'espère qu'elle aidera d'autres personnes avec le même problème:
override fun loadInitial(
params: LoadInitialParams<Int>,
callback: LoadInitialCallback<Int, ResultItem>
) {
mySocketClientRxRequest()
.subscribe ({
callback.onResult(it.resultItems 1, 2)
},{
it.printStackTrace()
})
}
à
override fun loadInitial(
params: LoadInitialParams<Int>,
callback: LoadInitialCallback<Int, ResultItem>
) {
mySocketClientRxRequest()
.blockingSubscribe ({
callback.onResult(it.resultItems 1, 2)
},{
it.printStackTrace()
})
}