it-swarm.dev

Biblioteca de paginação - Retorno de chamada de limite para rede + db, com API recebendo página e tamanho

Pergunta curta :

Qual é a maneira correta de lidar com o banco de dados + rede na biblioteca de Paginação dos componentes de Arquitetura, usando uma API que usa tamanho da página + para carregar uma nova página e a classe BoundaryCallback?

Pesquisa e explicação

Atualmente, a classe BoundaryCallback usada na biblioteca de paginação para componentes de arquitetura recebe como parâmetro a instância de um elemento na lista sem o contexto real de onde ele está. Isso acontece em onItemAtFrontLoaded e onItemAtEndLoaded.

Minha API deve receber a página e o tamanho da página para carregar o próximo bloco de dados. O retorno de chamada de limite, adicionado como parte do construtor de listas paginadas, deve informar quando carregar a próxima página de dados com base na distância de pré-busca e tamanho da página.

Como a API precisa do número da página e do tamanho da página para fornecer, não vejo uma maneira de enviá-la para a API, apenas recebendo um dos elementos da lista, conforme oferecido em onItemAtFrontLoaded e onItemAtEndLoaded. Verificando os exemplos do google em este link , eles usam o nome do último elemento para obter o próximo, mas isso não se encaixa em uma API com tamanho da página +.

Eles também têm outro exemplo com apenas rede que usa PagedKeyedDatasource , mas não há exemplo ou pista sobre como misturar isso com o banco de dados e o BoundaryCallback.

Editar : Apenas as soluções que encontrei até agora são armazenar a última página carregada nas preferências compartilhadas, mas isso parece um truque sujo.

Consulte https://github.com/googlesamples/Android-architecture-components/issues/252#issuecomment-392119468 para obter informações oficiais sobre ele.

56
droidpl

Eu implemento isso:

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

Digamos que você sempre busque N=10 itens por página no servidor e, em seguida, armazene-o no banco de dados. Você pode obter o número de itens em db usando a consulta sql SELECT COUNT(*) FROM tbl e armazená-lo na variável count. Agora, para obter o número da página que deve ser solicitado a seguir, use:

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

O documentation tem a dizer sobre o problema:

Se você não estiver usando uma API de rede com chave de item, poderá usar chave de página ou indexação de página. Se for esse o caso, a biblioteca de paginação não sabe sobre a chave da página ou o índice usado no BoundaryCallback, portanto, você precisa acompanhá-lo. Você pode fazer isso de duas maneiras:

Chave da página de armazenamento local

Se você deseja retomar perfeitamente sua consulta, mesmo que o aplicativo seja encerrado e reiniciado, você pode armazenar a chave no disco. Observe que, com uma API de rede de índice posicional/de página, existe uma maneira simples de fazer isso, usando o listSize como uma entrada para o próximo carregamento (ou listSize/NETWORK_PAGE_SIZE, para indexação de página). O tamanho da lista atual não é passado para o BoundaryCallback. Isso ocorre porque o PagedList não sabe necessariamente o número de itens no armazenamento local. Os espaços reservados podem estar desabilitados ou o DataSource pode não contar o número total de itens.

Em vez disso, para esses casos posicionais, você pode consultar o banco de dados quanto ao número de itens e passá-lo para a rede.

Chave da página na memória

Geralmente, não faz sentido consultar a próxima página da rede se a última página que você buscou foi carregada muitas horas ou dias antes. Se você mantiver a chave na memória, poderá atualizar sempre que começar a paginar a partir de uma fonte de rede. Armazene a próxima chave na memória, dentro do seu BoundaryCallback. Ao criar um novo BoundaryCallback ao criar um novo LiveData/Observable of PagedList, atualize os dados. Por exemplo, no Paging Codelab, o índice da página de rede do GitHub é armazenado na memória.

E links para um exemplo Codelab: https://codelabs.developers.google.com/codelabs/Android-paging/index.html#8

0
Luke