
Cortesia de Andrés Nieto Porras (https://www.flickr.com/photos/anieto2k)
Couchbase Lite executa replicações (sincronizações) usando threads em segundo plano. O início e a interrupção das replicações não ocorrem de forma síncrona. Isso pode levar a erros na detecção do estado de uma replicação.
O Classe de replicação tem, dependendo da plataforma, um em execução
ou uma rotina de conveniência como isRunning()
. Essa é uma maneira leve de verificar o status de uma replicação.
No entanto, seu uso pode levar a resultados inesperados. Por exemplo, recentemente escrevi um utilitário que usa replicações contínuas. Tenho um botão de alternância para iniciá-las e interrompê-las. É tentador usar o isRunning
para atualizar o estado do botão. Acontece que essa é uma má ideia. Não é de surpreender, já que as alterações ocorrem em segundo plano, mas é fácil ignorar.
Em vez disso, a abordagem preferida usa um ouvinte de alterações. Veja um exemplo.
Temos duas classes. A classe auxiliar de banco de dados engloba algumas operações padrão para simplificar. Adicionei uma interface para empregar um padrão de retorno de chamada. A classe cliente precisa implementá-la. A classe auxiliar digere a notificação de alteração do Couchbase Lite antes de passar qualquer coisa para o cliente. Isso proporciona uma boa separação de preocupações.
As listagens de códigos abaixo são resumidas. Elas mostram apenas o essencial. Vamos dar uma olhada na classe auxiliar primeiro.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
público classe Ajudante DB implementa Replicação.ChangeListener { privado booleano replicationActive = falso; privado Lista Ouvintes de estado = novo ArrayList<>(); ... público interface Ouvinte de estado de replicação { vazio onChange(booleano isActive); } público vazio startReplication(URL portal, booleano contínuo) { ... pushReplication.addChangeListener(este); pushReplication.iniciar(); } público vazio stopReplication() { ... } público vazio addReplicationStateListener(Ouvinte de estado de replicação ouvinte) { Ouvintes de estado.adicionar(ouvinte); } público vazio removeReplicationStateListener(Ouvinte de estado de replicação ouvinte) { Ouvintes de estado.remover(ouvinte); } // Replicação.ChangeListener @Override público vazio alterado(Replicação.ChangeEvent changeEvent) { se (changeEvent.getError() != nulo) { Lançável lastError = changeEvent.getError(); // Reagir ao erro retorno; } se (changeEvent.getTransition() == nulo) retorno; Estado da Replicação dest = changeEvent.getTransition().getDestination(); replicationActive = ((dest == Estado da Replicação.PARAR || dest == Estado da Replicação.PARADO) ? falso : verdadeiro); Ouvintes de estado.forEach(ouvinte -> ouvinte.onChange(replicationActive)); } } |
Vemos que o DBHelper implementa a função Replicação.ChangeListener
interface. Essa é uma interface definida pelo Couchbase Lite. Em startReplication
adicionamos esse ouvinte à replicação. Ele tem um método a ser substituído, alterado
. O ChangeEvent
transmitido pode ter vários valores diferentes. No exemplo, primeiro verifico se há erros e notifico o usuário se ocorrer algum. Caso contrário, verifico se esse é um evento de transição de estado de replicação. O estado de destino pode ser um dos seguintes INICIAL
, CORRIDA
, IDLE
, OFFLINE
, PARAR
ou PARADO
.
Nesse caso, só quero saber se a replicação está sendo encerrada, por isso simplifico o valor de retorno. Permito que os clientes registrem mais de um ouvinte, portanto, a última parte do código faz um loop em todas as callbacks e as invoca.
A classe cliente é ainda mais simples. Faço com que a classe implemente a interface necessária da classe auxiliar. Basta registrar o ouvinte durante a construção da instância e fazer com que onChange
faça o que for necessário na interface do usuário.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
público classe Cliente implementa Ajudante DB.Ouvinte de estado de replicação { privado Ajudante DB serviço = Ajudante DB.getInstance(); ... público Cliente() { serviço.addReplicationStateListener(este); } ... // DBHelper.ReplicationStateListener @Substituir público vazio onChange(booleano isActive) { // Código para lidar com a alteração } } |
Esse código foi extraído de uma ferramenta que criei. Leia sobre a própria ferramenta em esta postagemVocê pode encontrar o código-fonte no GitHub aqui.
Pós-escrito
Confira mais recursos em nosso portal do desenvolvedor e nos siga no Twitter @CouchbaseDev.
Você pode postar perguntas em nosso fóruns. E participamos ativamente de Estouro de pilha.
Entre em contato comigo no Twitter @HodGreeley
[...] vem da classe auxiliar DBService. Escrevi um pouco sobre como detectar o estado de uma replicação aqui. Para este aplicativo, só preciso saber se uma replicação está em execução ou não para manter o botão Sync [...]
[...] O outro ouvinte nos permite exibir um spinner de espera ocupada (barra de progresso indefinida) dependendo do estado da replicação. Você pode ler mais sobre o monitoramento do estado da replicação aqui. [...]