短い質問:
ページ+サイズを使用して新しいページとBoundaryCallback
クラスを読み込むAPIを使用して、アーキテクチャコンポーネントからページングライブラリでデータベース+ネットワークを処理する正しい方法は何ですか?
研究と説明
現在、アーキテクチャコンポーネントのページングライブラリで使用されているクラス BoundaryCallback
は、この要素がある場所の実際のコンテキストなしで、リスト内の要素のインスタンスをパラメーターとして受け取ります。 onItemAtFrontLoaded
およびonItemAtEndLoaded
で発生します。
私のApiは、次のデータチャンクをロードするためにページとページのサイズを受け取ることになっています。ページリストビルダーの一部として追加された境界コールバックは、プリフェッチ距離とページサイズに基づいて、データの次のページをいつ読み込むかを指示することになっています。
Apiはページ番号とページのサイズを提供する必要があるため、onItemAtFrontLoaded
およびonItemAtEndLoaded
で提供されているリストから要素の1つを受け取るだけでは、Apiに送信する方法がわかりません。 このリンク でGoogleの例を確認すると、最後の要素の名前を使用して次の要素を取得しますが、ページ+サイズのApiには適合しません。
また、 PagedKeyedDatasource
を使用するネットワークのみを使用した別の例もありますが、データベースとBoundaryCallbackとの混合方法に関するサンプルや手掛かりはありません。
Edit:これまでに見つけた解決策は、共有設定に最後に読み込まれたページを保存することですが、それは汚いトリックのように聞こえます。
公式の入力については、 https://github.com/googlesamples/Android-architecture-components/issues/252#issuecomment-392119468 を参照してください。
私はこれを実装します:
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;
}
サーバーからページごとに常に_N=10
_アイテムをフェッチし、それをdbに保存するとしましょう。 SQLクエリSELECT COUNT(*) FROM tbl
を使用してdbのアイテム数を取得し、変数count
に格納できます。次に要求されるページ番号を取得するには、次を使用します。
_val nextPage: Int = (count / N) + 1
_
documentation には、この問題について次のように記載されています。
アイテムキー付きネットワークAPIを使用していない場合は、ページキー付きまたはページインデックス付きを使用している可能性があります。この場合、ページングライブラリは、BoundaryCallbackで使用されるページキーまたはインデックスを認識しないため、自分で追跡する必要があります。これは、次の2つの方法のいずれかで実行できます。
ローカルストレージページキー
クエリを完全に再開したい場合は、アプリが強制終了されて再開された場合でも、キーをディスクに保存できます。位置/ページインデックスネットワークAPIでは、listSizeを次のロードへの入力として使用する(またはページインデックスの場合はlistSize/NETWORK_PAGE_SIZE)ことにより、これを行う簡単な方法があることに注意してください。ただし、現在のリストサイズはBoundaryCallbackに渡されません。これは、PagedListがローカルストレージ内のアイテムの数を必ずしも認識していないためです。プレースホルダーが無効になっているか、データソースがアイテムの総数をカウントしない場合があります。
代わりに、これらの定位置のケースでは、データベースにアイテムの数を照会し、ネットワークに渡すことができます。
メモリ内ページキー
フェッチした最後のページが何時間または何日も前にロードされた場合、ネットワークから次のページを照会することは意味がないことがよくあります。キーをメモリに保持しておくと、ネットワークソースからページングを開始するたびに更新できます。 BoundaryCallback内の次のキーをメモリに保存します。 PagedListの新しいLiveData/Observableを作成するときに新しいBoundaryCallbackを作成すると、データが更新されます。たとえば、Paging Codelabでは、GitHubネットワークページインデックスはメモリに保存されます。
サンプルCodelabへのリンク: https://codelabs.developers.google.com/codelabs/Android-paging/index.html#8