O Google tem o compromisso de promover a igualdade racial para as comunidades negras. Saiba como.

Implementar uma solicitação personalizada

Esta lição descreve como implementar os próprios tipos de solicitação personalizada, para tipos que não são diretamente compatíveis com o Volley.

Programar uma solicitação personalizada

A maioria das solicitações tem implementações prontas para uso na caixa de ferramentas. Se sua resposta for uma string, imagem ou JSON, você provavelmente não precisará implementar uma Request personalizada.

Nos casos em que é necessário implementar uma solicitação personalizada, basta fazer o seguinte:

  • Estenda a classe Request<T>, em que <T> representa o tipo de resposta analisada que a solicitação espera. Portanto, se a resposta analisada for uma string, por exemplo, crie a solicitação personalizada estendendo Request<String>. Consulte as classes da caixa de ferramentas do Volley StringRequest e ImageRequest para ver exemplos de como estender Request<T>.
  • Implemente os métodos abstratos parseNetworkResponse() e deliverResponse(), descritos em mais detalhes abaixo.

parseNetworkResponse

Uma Response encapsula uma resposta analisada para entrega, para determinado tipo (como string, imagem ou JSON). Veja um exemplo de implementação de parseNetworkResponse():

Kotlin

    override fun parseNetworkResponse(response: NetworkResponse?): Response<T> {
        return try {
            val json = String(
                    response?.data ?: ByteArray(0),
                    Charset.forName(HttpHeaderParser.parseCharset(response?.headers)))
            Response.success(
                    gson.fromJson(json, clazz),
                    HttpHeaderParser.parseCacheHeaders(response))
        }
        // handle errors
    // ...
    }
    

Java

    @Override
    protected Response<T> parseNetworkResponse(
            NetworkResponse response) {
        try {
            String json = new String(response.data,
            HttpHeaderParser.parseCharset(response.headers));
        return Response.success(gson.fromJson(json, clazz),
        HttpHeaderParser.parseCacheHeaders(response));
        }
        // handle errors
    // ...
    }
    

Observe o seguinte:

  • parseNetworkResponse() usa como parâmetro uma NetworkResponse, que contém o payload de resposta como um byte[], código de status HTTP e cabeçalhos de resposta.
  • Sua implementação precisa retornar um Response<T>, que contém o objeto de resposta digitado e os metadados do cache ou um erro, como no caso de uma falha de análise.

Se o protocolo tiver uma semântica de cache diferente do padrão, você mesmo poderá criar um Cache.Entry, mas a maioria das solicitações será compatível com algo como:

Kotlin

    return Response.success(myDecodedObject,
            HttpHeaderParser.parseCacheHeaders(response))
    

Java

    return Response.success(myDecodedObject,
            HttpHeaderParser.parseCacheHeaders(response));
    

O Volley chama parseNetworkResponse() de uma linha de execução de worker. Isso garante que operações caras de análise, como decodificar um JPEG em um bitmap, não bloqueiem a linha de execução de IU.

deliverResponse

O Volley leva você novamente para a linha de execução principal com o objeto retornado em parseNetworkResponse(). A maioria das solicitações invoca uma interface de callback aqui, por exemplo:

Kotlin

    override fun deliverResponse(response: T) = listener.onResponse(response)
    

Java

    protected void deliverResponse(T response) {
            listener.onResponse(response);
    

Exemplo: GsonRequest

Gson (link em inglês) é uma biblioteca para a conversão de objetos Java de e para JSON por meio de reflexão. Você pode definir objetos Java com o mesmo nome das chaves JSON correspondentes, passar ao Gson o objeto de classe, e o Gson preencherá os campos. Veja uma implementação completa de uma solicitação do Volley que usa o Gson para análise:

Kotlin

    /**
     * Make a GET request and return a parsed object from JSON.
     *
     * @param url URL of the request to make
     * @param clazz Relevant class object, for Gson's reflection
     * @param headers Map of request headers
     */
    class GsonRequest<T>(
            url: String,
            private val clazz: Class<T>,
            private val headers: MutableMap<String, String>?,
            private val listener: Response.Listener<T>,
            errorListener: Response.ErrorListener
    ) : Request<T>(Method.GET, url, errorListener) {
        private val gson = Gson()

        override fun getHeaders(): MutableMap<String, String> = headers ?: super.getHeaders()

        override fun deliverResponse(response: T) = listener.onResponse(response)

        override fun parseNetworkResponse(response: NetworkResponse?): Response<T> {
            return try {
                val json = String(
                        response?.data ?: ByteArray(0),
                        Charset.forName(HttpHeaderParser.parseCharset(response?.headers)))
                Response.success(
                        gson.fromJson(json, clazz),
                        HttpHeaderParser.parseCacheHeaders(response))
            } catch (e: UnsupportedEncodingException) {
                Response.error(ParseError(e))
            } catch (e: JsonSyntaxException) {
                Response.error(ParseError(e))
            }
        }
    }
    

Java

    public class GsonRequest<T> extends Request<T> {
        private final Gson gson = new Gson();
        private final Class<T> clazz;
        private final Map<String, String> headers;
        private final Listener<T> listener;

        /**
         * Make a GET request and return a parsed object from JSON.
         *
         * @param url URL of the request to make
         * @param clazz Relevant class object, for Gson's reflection
         * @param headers Map of request headers
         */
        public GsonRequest(String url, Class<T> clazz, Map<String, String> headers,
                Listener<T> listener, ErrorListener errorListener) {
            super(Method.GET, url, errorListener);
            this.clazz = clazz;
            this.headers = headers;
            this.listener = listener;
        }

        @Override
        public Map<String, String> getHeaders() throws AuthFailureError {
            return headers != null ? headers : super.getHeaders();
        }

        @Override
        protected void deliverResponse(T response) {
            listener.onResponse(response);
        }

        @Override
        protected Response<T> parseNetworkResponse(NetworkResponse response) {
            try {
                String json = new String(
                        response.data,
                        HttpHeaderParser.parseCharset(response.headers));
                return Response.success(
                        gson.fromJson(json, clazz),
                        HttpHeaderParser.parseCacheHeaders(response));
            } catch (UnsupportedEncodingException e) {
                return Response.error(new ParseError(e));
            } catch (JsonSyntaxException e) {
                return Response.error(new ParseError(e));
            }
        }
    }
    

O Volley disponibiliza as classes JsonArrayRequeste JsonArrayObject prontas para uso, caso você prefira adotar essa abordagem. Consulte Fazer uma solicitação padrão para mais informações.