Olá desenvolvedores Android,

Chegamos a terceira parte da série de posts sobre comunicação web em apps Android (veja a primeira e segunda partes), onde a idéia é falar sobre um framework que foi apresentado no Google I/O de 2013: Volley.

Nos posts anteriores, a idéia foi mostrar os conceitos e bases da comunicação web em apps Android, para que você compreenda como é feita essa comunicação e pudesse assim, usar da maneira mais adequada para o seu app. Mas como deve ter percebido, talvez até na prática, esses trechos de código para comunicação acabam se repetindo em diversos projeto ou até vários pontos do seu app. O que nos leva a pensar que isso deveria estar em uma biblioteca, não é verdade?

Quando usar Volley ?


É no sentido de poupar tempo e facilitar as operações básicas que foi criada a Volley, que ajuda a realizar requisições, tratar respostas, trabalhar com filas de requisições, prioridades e também oferece cache, assim você pode rapidamente ter dados disponíveis em seu app.
Mas, não é uma biblioteca que se aplica em todas as situações. As respostas são entregues inteiras diretamente na memória, o que torna a Volley uma opção não indicada para grandes quantidades de dados como vídeos e música. Ou seja, é a escolha ideal para requisições menores, como consumo de APIs JSON, XML e arquivos menores como imagens.

Integrando a Volley ao seu projeto Android


Todo o código do framework está disponível juntamente com todo o código do Android Open Source Project. Dessa forma, há diversas maneiras de importar o código e integrá-lo com o seu projeto Android, vamos ver algumas dessas opções:

  • Copiar o código para o seu projeto Android
  • Gerar um JAR do código e importar como biblioteca
  • Se utilizar Git para o controle de versão do seu projeto, pode adicionar o framework Volley como um sub-módulo do seu projeto.
Para todos os casos citados acima, é necessário antes fazer o clone do repositório do projeto e então executar os passos que desejar. Para esse post, vamos considerar que já tem a biblioteca pronta para uso. Caso tenha algum problema, veja essa pergunta no Stackoverflow.

Comunicação com Requests


Na Volley, toda a comunicação web e até o tratamento de cache é através de requisições. E o principal mecanismo para isso, é uma fila de requisições, a RequestQueue. Essa fila é utilizada em todos os pontos da aplicação, como uma forma de centralizar todo o fluxo de comunicação. Inclusive permitindo priorizar requisições dentro dessa fila.

Como a RequestQueue vai ser utilizada em toda a aplicação, uma maneira de ter apenas uma instância da fila e dar fácil acesso a todas os outros componentes do seu app, é criar uma classe que estende de Application e registrá-la no Manifest, veja o exemplo:

VolleySampleApplication
public class VolleySampleApplication extends Application {

    private RequestQueue queue;

    @Override
    public void onCreate() {
        this.queue = Volley.newRequestQueue(this);
    }

    public RequestQueue getRequestQueue() {
        return queue;
    }
}

AndroidManifest
    <application
        android:name=".VolleySampleApplication"
        android:allowBackup="true"
        ...
    </application>

Criando e enviando uma requisição por POST


Para seguir o exemplo que foi utilizado no post anterior, vamos fazer uma requisição e enviar por POST para consumir o mesmo webservice do exemplo anterior, que irá contar quantas palavras há na frase enviada por parâmetro e devolver um JSON com a quantidade de palavras e a frase original.

No trecho abaixo, está a criação da requisição e a inclusão dos parâmetros, que é feita sobrescrevendo o método getParams(). Depois,  a requisição é adicionada à fila e será executada pela Volley. Veja o trecho completo:
  StringRequest strReq = new StringRequest(Request.Method.POST, url, 
          this, this) {
      @Override
      protected Map getParams(){
          Map params = new HashMap();
          params.put("text", textEditText.getText().toString());

          return params;
      }
  }
  VolleySampleApplication app = (VolleySampleApplication) 
      getApplication();
  app.getRequestQueue().add(strReq);

Como o servidor responde um JSON, a primeira idéia pode ser em utilizar uma JsonObjectRequest, mas esse tipo de requisição não executa o método getParams(), já que utiliza o corpo da requisição para enviar o JSON esperado pela requisição. Assim, caso você tente adicionar parâmetros a requisição, verá que eles nunca irão chegar ao servidor. Por isso, foi escolhido uma StringRequest e o seu retorno será convertido para um objeto JSON.

Na criação da request, o terceiro e quarto parâmetros representam os listeners para sucesso e falha da requisição,  nesse caso a própria Activity será o listener para ambos os casos. Abaixo está o código para tratamento da String recebida, sua conversão para JSON e então, a atualização da interface com o número de palavras na frase:
  @Override
  public void onResponse(String s) {
      if (s != null) {
          try {
              JSONObject jsonObject = new JSONObject(s);
              if (jsonObject != null) {
                  int words = jsonObject.getInt("words");
                  updateWordsCount(words);
              }
          } catch (JSONException e) {
              e.printStackTrace();
          }
      }
  }

  @Override
  public void onErrorResponse(VolleyError volleyError) {
      volleyError.printStackTrace();
  }

Você deve levar em consideração que esse é um código de exemplo, então para que não tenha que sobrescrever o método getParams() todas as vezes, deixando seu código muito extenso e com uma legibilidade ruim, seria uma boa idéia considerar o encapsulamento desse processo em alguma classe auxiliar, e também retirar o código de tratamento do JSON da Activity.

Cache


Uma funcionalidade muito poderosa na Volley é o cache. Para não deixar o post muito grande, não vamos entrar em detalhes, mas o principal ponto é que é possível armazenar o cache de acordo com a requisições. Assim, é possível ter resultados rápidos para casos onde se realizam repetidas requisições ou até, para uma eventual falta de conectividade.
Cada requisição pode ser armazenada ou removida individualmente, e até todo o cache pode ser invalidado de uma só vez, conforme a necessidade. Também é possível tratar a data em que a inclusão no cache foi feita, e baseado na existência ou tempo de vida do cache, tomar a decisão se deve ser feita a requisição ou não.

Prioridade


Quando se trabalha com muitas requisições dentro de um aplicativo, em algum momento pode se desejar que alguma requisição seja tratada com alguma prioridade. Apesar de não ter um método como setPriority(), é possível fazer algo parecido como foi feito para a getParams() e sobrescrever o método getPriority() e setPriority().

Mais detalhes


Para saber mais sobre a Volley, assista o vídeo Volley: Easy, Fast Networking for Android do Google I/O de 2013, de quando a biblioteca foi apresentada.
E para o exemplo completo dos códigos utilizados aqui, veja o projeto VolleySample disponível no GitHub.

Fique a vontade para deixar seu comentário, compartilhar esse post e também, estamos disponíveis através da página +Desenvolvedores Google, onde você pode conversar com outros desenvolvedores Android e trocar experiências sobre comunicação Web em aplicativos Android.

+Neto Marin
Developer Advocate