Consumindo Web Service No Android
Uma tarefa muito comúm do dia a dia seria realizar requisições HTTP e consumir Web Services, mas as vezes pode ser um tanto quanto chata pois precisa de configurações e alguns passos a serem seguidos.
Para exemplo do post, vamos consumir um serviço para buscas de CEP, os passos que deveriamos seguir são:
- Desenhar o layout
- Consumir nosso serviço
- Mostrar os dados consumidos para o usuário
Após concluir todos esses passos teremos nossa app funcionando da seguinte maneira:
Desenhando nossa app
O primeiro passo será criar o layout da nossa app, como o assunto do post refere-se ao web service, irei disponibilizar o layout:
Após adicionar esse layout para a activity, devemos ter nossa app parecido com:
Consumindo um serviço
Agora que o layout esta pronto, podemos começar a consumir nosso serviço, para isso alguns passos devem ser seguidos, sendo eles:
- Adicionar um listener no botão Buscar CEP
- Validar se o CEP foi digitado
- Realizar a busca do CEP
- Mostrar os dados para o usuário
Adicionando um listener no botão
Primeiro vamos começar adicionando um listener em nosso botão, para quando ele for clicado realizar alguma função, mas como podemos fazer isso ? Para trabalhar com eventos de click em botões podemos utilizar o setOnClickListener
.
Vamos buscar nosso botão e atribuí-lo em uma variável:
Agora precisamos adicionar o listener no botão:
Pronto, com isso já devemos ser capazes de escutar e emitir alguma função quando o botão for clicado.
Criando a classe para buscar o CEP
Para realizar a busca do CEP vamos criar uma classe responsável por esse requisição HTTP:
Vou chamar a classe de HttpService
pois a mesma irá consumir um serviço HTTP. Aqui entra um detalhe, toda requisição HTTP deve ser feita em background pelo Android, ou seja, a mesma não pode ser feita na thread principal, mas porque isso ocorre ?
Entendendo como uma requisição HTTP funciona
Uma requisição HTTP é feita da seguinte maneira:
- Primeiro devemos configurar a requisição(URL, cabeçalhos e resposta)
- Depois de configurada podemos realizar a requisição
- Durante o processo de requisição devemos aguardar o servidor responsável processa-la
- Após o servidor processa-la podemos pegar o retorno
Veja que no terceiro passo não sabemos quanto tempo o servidor irá levar para conseguir processar a requisição e devolver a resposta para a gente, por isso o Android exige que a requisição seja feita em background, assim o app não irá travar ou ficar congelado para o usuário enquanto a requisição é realizada.
Beleza Matheus, agora sabemos o motivo do Android exigir que a requisição seja feita em background ou em segundo plano, mas como podemos fazer isso ?
Adaptando nossa classe
O primeiro passo será extender a classe AsyncTask
do Android responsável por realizar tarefas em background.
Opa, espera ae Matheus, que doidera é essa de Void, Void, CEP
?
Parâmetros do AsyncTask
Calma, vamos devagar, para tudo tem uma explicação, sempre que extendemos a AsyncTask
devemos passar esse três parâmetros para ela, sendo eles:
- Primeiro: Será o tipo de parâmetro enviado para a execução da classe
- Segundo: Será o tipo de parâmetro recebido no método
onProgressUpdate
(não iremos utiliza-lo, o mesmo é chamado sempre que a requisição é atualizada, ideal para barras de progresso) - Terceiro: Será o tipo de retorno da classe
Criando o modelo CEP
Repare que o terceiro parâmetro da AsyncTask
é uma classe CEP
, mas ainda não temos ela, então vamos cria-la:
Veja que trata apenas de uma classe para representar e armazenar as informações de nosso CEP, não tem segredo.
Bom, agora que já extendemos a classe AsyncTask
e conseguimos entender seus parâmetros, devemos sobrescrever o método responsável pela execução em background:
Realizando a requisição em background
O único método que somos obrigados a sobrescrever quando extendemos de AsyncTask
é o doInBackground
, como o próprio nome já diz, será o método responsável por realizar a requisição para nosso web service em background.
Para realizar a requisição precisamos de um CEP, mas em nossa classe não recebemos ele ainda, como podemos resolver o problema ? Se nossa classe HttpService
precisa de um CEP para funcionar, porque não passar o CEP pelo construtor ? Assim garantimos que sempre ela terá um CEP ao ser instânciada(usada):
Veja que agora já possuímos um CEP para buscar os dados. O primeiro passo para nossa requisição funcionar será validar o CEP digitado e passado para nossa classe:
Repare que agora estamos validando se foi passado um CEP e se o mesmo contém oito dígitos.
Configurando e realizando a requisição
Vamos começar a configurar nossa requisição, o primeiro passo é termos uma URL
para consumirmos:
Durante a construção da URL
pode acontecer de passarmos uma inválida ou que não existe, por isso, devemos realizar um tratamento de exceção com try catch
:
Agora precisamos abrir uma conexão e configurar os cabeçalhos dela(Tipo de requisição, tipo de retorno, tempo máximo de espera, etc…):
Com as configurações realizadas, precisamos de fato, realizar a conexão, ou seja, conectar em nossa url
:
Pronto, ja conseguimos conectar, mas não basta conectar e realizar a requisição, precisamos de fato pegar a resposta e salvar em alguma variável, como podemos fazer isso ?
Lendo a resposta da requisição
Podemos ler a resposta facilmente com a classe Scanner
do pacote java.io
, ela abstrai bastante a complexidade de ler informações:
Beleza, estamos criando nosso scanner
mas de onde ele vai ler as informações ? Para isso temos o método openStream
em nossa url
:
Como quase todas as classes do pacote java.io
, devemos tratar a exceção para arquivos não encontrados, como já temos nosso try catch
, precisamos apenas adicionar mais um catch
em nosso try
:
Agora, com as exceções tratadas e nosso scanner
recebendo as informações, já podemos realizar a leitura da resposta:
Beleza, tudo certo ? Errado, até o momento lemos a resposta e passamos para a classe StringBuilder
, porém, lembra que o terceiro parâmetro de nosso AsyncTask
era do tipo CEP
? Pois é, sendo assim precisaremos retornar um CEP
em nosso método doInBackground
, pois até agora temos um JSON lido dentro de uma String:
Afinal, como podemos pegar esse JSON, gravar dentro de uma String
e converte-lo para a classe CEP
?
Convertendo dados do json
Realizar a conversão de dados em Java pode ser algo trabalhoso, sabendo isso, a Google lançou uma biblioteca chamada GSON, responsável em abstrair a complexidade na hora de converter dados relacionados com JSON, para começar a usa-la, devemos declarar a dependência em nosso build.gradle
:
Depois de adicionar a dependência, realize o sincronismo do Gradle.
Retornando um CEP
Com nosso GSON instalado, podemos converter nosso JSON para um objeto do tipo CEP da seguinte maneira:
Muito simples não ?
Agora que nossa classe responsável por realizar a requisição esta pronta, podemos utilizada em listener de nosso botão. Caso tenha se perdido em algum passo, segue a classe completa:
Retornando os dados para o usuário
Bom, até o momento de todos os passos que deveriamos realizar:
- Adicionar um listener no botão Buscar CEP
- Validar se o CEP foi digitado
- Realizar a busca do CEP
- Mostrar os dados para o usuário
Ja concluímos os três primeiros, portanto, precisamos apenas retornar os dados para o usuário.
Buscando os dados do CEP
Vamos começar buscando os dados do CEP digitado em nosso app, para isso já haviamos criado o listener, precisamos apenas fazer uso da nossa classe HttpService
:
Com isso iremos ter o seguinte resultado:
Caso tenha ficado alguma dúvida, você pode encontrar o projeto completo aqui, também gravei um vídeo no meu canal mostrando a parte prática da implementação: