web-dev-qa-db-ja.com

ページングライブラリ-ページとサイズを取得するAPIを使用したネットワーク+データベースの境界コールバック

短い質問

ページ+サイズを使用して新しいページと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 を参照してください。

56
droidpl

私はこれを実装します:

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;
}
1
user3795295

サーバーからページごとに常に_N=10_アイテムをフェッチし、それをdbに保存するとしましょう。 SQLクエリSELECT COUNT(*) FROM tblを使用してdbのアイテム数を取得し、変数countに格納できます。次に要求されるページ番号を取得するには、次を使用します。

_val nextPage: Int = (count / N) + 1
_
0
realpac

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

0
Luke