Realtime Databases — Parte 2
Hello a todos Devs.
No último post escrevi sobre como os dados são estruturados na realtime database e como utilizar a console para escrever e visualizar estes dados.
Neste post irei explicar como conectar uma android app ao Firebase realtime database para poder fazer a leitura e escrita de dados.
Configuração do Projecto
Antes de poder conectar uma app ao Firebase, é necessário fazer algumas configurações dos dois lados que incluem a criação de um ficheiro com todas as informações(API_KEYS, SHA1) sobre o cliente(Aplicação Android), configuração das dependências para poder utilizar as bibliotecas do Firebase correspondentes ao serviço que se quer utilizar.
1 . Criar uma aplicação android no Firebase e baixar o ficheiro de configuração
Dentro do Firebase console, devemos clicar na primeira opção no canto superior esquerdo que nos mostrará um em janela em que podemos fazer a gestão ou adicionar novas aplicações. Ao clicar em “Add App” podemos escolher o tipo de app que queremos adicionar das três opções disponíveis android, iOS e Web.
Ao seleccionar uma das opções, será aberto um wizzard que irá pedir que seja inseridas informações necessárias para a identificação de cada tipo de cliente pelo Firebase.
Para o nosso caso, escolhemos a opção “Add firebase to your android app” e um wizzard é aberto pedido que seja disponibilizado o package name da aplicação e o certificado SHA1.
Só estes dois campos são pedidos porque a combinação destes 2 elementos é única para todas as aplicações em disponíveis no playstore pois o packagename é utilizado como um identificador único da aplicação no playstore e caso esta app seja certificada utilizando uma certa chave só poderá ser actualizada utilizando a mesma.
Depois de inserir os dados, o Firebase irá apresentar um botão para baixar o ficheiro de configuração que dever ser copiado para dentro do modulo “app” do nosso projecto.
Com o ficheiro copiado, o próximo passo para configuração é definir o plugin do Google Play services copiando a linha classpath ‘com.google.gms:google-services:3.0.0' para o ficheiro build.gradle do projecto e de seguida fazer o apply do plugin no ficheiro build.gradle do module “app” utilizando a linha apply plugin: ‘com.google.gms.google-services’ que deve ser a última linha do ficheiro.
O último passo da configuração consiste em simplesmente declarar as bibliotecas externas específicas ao Firebase que vamos utilizar no projecto colocando dentro da secção de dependências no ficheiro build.gradle do module “app”.
Para utilizar a realtime database, devemos colocar nas dependências a linha ‘com.google.firebase:firebase-database:9.2.0’ , fazer a sincronização do projecto e já está.
Leitura/Escrita dos dados a realtime database
Escrever ou ler os dados no Firebase pode ser feito de forma muito simples seguindo os seguintes passos:
- Pegar a instância a base de dados
Dentro da Activity ou Fragment devemos primeiramente pegar a instância da realtime database simplesmente criando um objecto da classe FirebaseDatase e atribuir a instância da realtime database fazendo Firebase.getInstance(). - Pegar a referência
Após ter a instance para a realtime database, podemos então de forma deliberada escolher o local da base de dados que queremos fazer a leitura de dados utilizando o método getReference() que nos coloca na raiz da nossa JSON tree ou getReference(String caminho) que nos coloca no caminho especificado na string.
Se tomarmos como exemplo a imagem abaixo, o método getReference() nos levaria para a https://codelab-speedupafrica.firebaseio.com/ e getReference(“items/ -KKj3RLhWbLpETzy_eki”) nos colocaria na raiz do nó correspondente ao item.
Esta referência pode ser utilizada de duas formas, em que a primeira consiste em utilizar a classe DatabaseReference para ler dados, escrever, criar outras referências ou a classe Query que é uma subclasse da DatabaseReference utilizada para construir queries com diferentes parâmetros para a leitura dos dados(Entrarei em detalhes nos próximos posts).
3. Registar os listeners e fazer a leitura dos dados
Para poder ler os dados da realtime database precisamos de listeners a referência de tal forma que a nossa aplicação sempre receba notificações sobre qualquer tipo de evento que adicionem,modifiquem ou apague os dados.
O Firebase oferece dois listeners que podemos utilizar nomeadamente ValueEventListener e ChildEventListener.
ValueEventListener
O ValueEventListener quando registado a uma referência da realtime database, irá retornar os dados do nó em que foi registado e continuará a monitorar para qualquer tipo de mudança.
Este listener contem o método onDataChanged que nos retorna a informação no caminho registado no formato DataSnapshot.
DataSnapshop é simplesmente a representação da realtime database e um certo caminho no momento e que registamos um listener.
Para que possamos extrair os dados do DataSnapshop é preciso utilizar o método getValue() em que:
- getValue(String chave) pode ser utilizado para pegar o valor da chave passada ao método( Ex: String itemName = datasnapshot.getValue(“item_name”))
- getValue(Class.class) pode ser utilizado para automaticamente converter o DataSnapshot para a classe passada.
É preciso tomar sempre atenção a forma como os dados estão estruturados e para o caso dos nós que representem um objecto com diferentes atributos a sua classe equivalente deverá conter o nome das variáveis escritas da mesma forma que as chaves na base de dados.
ChildEventListener
O ChildEventListener quando registado a um certo caminho na realtime database irá retornar os dados daquele caminho e ficará a escuta de qualquer tipo de evento que adicione ou modifique os dados no caminho.
Para melhor entender, vamos tomar como exemplo a estrutura da foto abaixo em que temos o nó items com diferentes filhos que por sua vez possuem vários atributos.
Registando o ValueEventListener ao nó items este listener iria retornar um DataSnapshot com a lista de todos elementos e nos casos em que um elemento é modificado ou removido seria retornado um DataSnapshot com todos elementos incluindo o modificado ou um novo DataSnapshot com a lista sem o elemento que foi removido respectivamente.
Diferentemente do ValueEventListener, o ChildEventListener no mesmo cenário que o anterior, iria retornar e ficar a escuta de cada elemento do nó items de forma separada pelos seguintes métodos de callback:
onChildAdded(DataSnapshot): retorna item por item ao ler os dados da lista em que o listener está registado ou sempre que um elemento for adicionado a lista.
onChildChanged(DataSnapshot): retorna o elemento modificado da lista do nó em que o listener esta registado.
onChilMoved(DataSnapshot): retorna o elemento que mudou de posição na lista do nó em que o listener esta registado.
onChildRemoved(DataSnapshot): retorna o elemento removido da lista do nó em que o listener esta registado.
Ler dados na realtime database é extremamente fácil utilizando um dos listeners acima mas escrever consegue ser ainda mais fácil.
Escrever a uma realtime database consegue ser mais fácil devido ao facto desta ser uma árvore de objectos JSONs como explicado no post anterior e este simples facto faz com que seja possível manipular os dados como faríamos em um outro ficheiro JSON simplesmente especificando o valor e a chave.
Imaginando que queremos modificar o nome de um dos items do nó items ilustrado na figura anterior, teríamos de simplesmente seguir 2 passos:
- Criar uma instância da DatabaseReference com o caminho até o objecto ou atributo que queremos modificar/adicionar.
- Simplesmente utilizando o metodo setValue() passando o valor desejado como argumento.
itemRef=mDatabase.getReference().child("items").child(itemId).child("name");
mItemsRef.setValue("Novo Nome do Item");
Se ao invés de escrever ou modificar o valor de uma determinada chave quisermos escrever/modificar um conjunto (Exemplo: Todos os atributos do objecto que representam um item) poderíamos simplesmente o fazer passando um Objecto da classe cujo os atributos são os que desejamos escrever/modificar ou simplesmente criar um Map ou HashMap, inserir os valores as respectivas chaves e finalmente passar o hashmap para o método setValue.
PS: Os nomes dos atributos nas classes, ou das chaves no Hashmap/Map deve ser obrigatoriamente igual ao das chaves correspondentes dos dados guardados na realtime database que queiramos modificar pois caso haja alguma diferença esta será considerada como uma nova chave que será adicionada e o valor atribuído a ela e não a que pretendíamos modificar.
E desta forma chegamos ao fim de mais um post da série sobre o firebase, aprendendo sobre a configuração de um projecto android para poder escrever e ler dados para a realtime database.
Para o próximo post, iremos cobrir como utilizar o serviço firebase Auth para que possamos depois falar sobre as regras de segurança “security rules” e garantir a devida autorização dos utilizadores ao ler o escrever para a nossa realtime database.
Se tens alguma curiosidade ou questão, deixe um comentário e bora conversar.
Abraços, DM :)