
O Retrofit é uma biblioteca conhecida entre os desenvolvedores do Android por redes, alguns até consideram um padrão de alguma forma. Há muitas razões para essa popularidade: a biblioteca suporta perfeitamente a API REST, é facilmente testada e configurada, e os pedidos pela rede com sua ajuda são realizados com muita simplicidade. Neste artigo, mostrarei como configurar e usar o Retrofit para implementar a rede com seu aplicativo.
Configurar Retrofit
Inclua a seguinte dependência no arquivo build.gradle
:
implementation 'com.squareup.retrofit2:retrofit:2.4.0'
Usaremos o Gson para converter JSON em POJO. O retrofit fornece uma dependência que converte automaticamente JSON em POJO. Para fazer isso, adicione outra dependência ao arquivo build.gradle
:
implementation 'com.squareup.retrofit2:converter-gson:2.3.0'
Se o seu aplicativo ainda não tiver permissão para trabalhar com a rede, adicione a linha correspondente ao arquivo AndroidManifest
:
<uses-permission android:name="android.permission.INTERNET"/>
Depois que as dependências são adicionadas, precisamos escrever um código para configurar a biblioteca Retrofit.
Crie uma classe chamada NetworkService
:
public class NetworkService { }
Esta classe deve ser um objeto singleton, portanto, declare uma variável estática e uma função que crie e retorne uma variável do mesmo tipo que a classe. Se você não souber como esse padrão funciona, consulte este artigo , que contém exemplos de implementações na linguagem Java.
public class NetworkService { private static NetworkService mInstance; public static NetworkService getInstance() { if (mInstance == null) { mInstance = new NetworkService(); } return mInstance; } }
Para teste, usamos o JSONPlaceholder , que fornece uma API REST online falsa para desenvolvedores:
https://jsonplaceholder.typicode.com
Agora declararemos e inicializaremos o Retrofit no construtor NetworkService
:
public class NetworkService { private static NetworkService mInstance; private static final String BASE_URL = "https://jsonplaceholder.typicode.com"; private Retrofit mRetrofit; private NetworkService() { mRetrofit = new Retrofit.Builder() .baseUrl(BASE_URL) .addConverterFactory(GsonConverterFactory.create()) .build(); } public static NetworkService getInstance() { if (mInstance == null) { mInstance = new NetworkService(); } return mInstance; } }
A configuração está concluída, agora precisamos determinar os pontos de extremidade que retornarão dados.
Adicionando terminais
Crie uma interface chamada JSONPlaceHolderApi
:
public interface JSONPlaceHolderApi { }
No site JSONPlaceHolder, URL /posts/id
é o terminal que retorna uma mensagem com o identificador apropriado. Este terminal recebe uma solicitação GET e retorna dados no formato JSON da seguinte maneira:
{ "userId": 1, "id": 1, "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit", "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto" }
Primeiro, criaremos o POJO apropriado para a resposta JSON:
public class Post { @SerializedName("userId") @Expose private int userId; @SerializedName("id") @Expose private int id; @SerializedName("title") @Expose private String title; @SerializedName("body") @Expose private String body; public int getUserId() { return userId; } public void setUserId(int userId) { this.userId = userId; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getBody() { return body; } public void setBody(String body) { this.body = body; } }
Como você pode ver, esta é uma classe POJO simples. @SerializedName()
as variáveis usando @SerializedName()
, passando o nome para lá. Esses nomes são realmente chaves nos dados JSON retornados da API, para que você possa alterar o nome da variável como desejar, mas verifique se o nome passado para a anotação @SerializedName()
está exatamente presente no JSON.
Na interface criada acima, defina os terminais com os parâmetros necessários:
public interface JSONPlaceHolderApi { @GET("/posts/{id}") public Call<Post> getPostWithID(@Path("id") int id); }
Como enviamos uma solicitação GET, precisamos aplicar a anotação @GET
ao método, dentro do qual é o terminal para o qual queremos enviar a solicitação. Como você pode ver, não estamos adicionando o URL completo, pois A BASE_URL
automaticamente pega o BASE_URL
passado para a classe NetworkService
e o adiciona ao restante da URL.
O tipo de retorno do método é chamado de Call<Post>
. Call
é uma classe fornecida diretamente pela própria biblioteca. E todos os métodos na interface devem retornar valores desse tipo. Esta é uma classe genérica que aceita o tipo de objeto que queremos converter para JSON. Passamos pelo Post
porque este é exatamente o objeto no qual queremos converter a resposta JSON. Passamos um número inteiro para os parâmetros e o anotamos usando @Path
, dentro do qual escrevemos id
. A modernização assumirá esse valor e no terminal substituirá {id}
. Portanto, se passarmos o valor 1 como parâmetro, o terminal será semelhante a /posts/1
; se passarmos o valor 10, o terminal será /posts/10
.
Agora precisamos do Retrofit para fornecer uma implementação da interface JSONPlaceHolderApi
. Para fazer isso, use o método create()
:
public class NetworkService { private static NetworkService mInstance; private static final String BASE_URL = "https://jsonplaceholder.typicode.com"; private Retrofit mRetrofit; private NetworkService() { mRetrofit = new Retrofit.Builder() .baseUrl(BASE_URL) .addConverterFactory(GsonConverterFactory.create()) .build(); } public static NetworkService getInstance() { if (mInstance == null) { mInstance = new NetworkService(); } return mInstance; } public JSONPlaceHolderApi getJSONApi() { return mRetrofit.create(JSONPlaceHolderApi.class); } }
Em seguida, você precisa obter o JSONPlaceHolderApi
do NetworkService
e enviar uma solicitação:
NetworkService.getInstance() .getJSONApi() .getPostWithID(1) .enqueue(new Callback<Post>() { @Override public void onResponse(@NonNull Call<Post> call, @NonNull Response<Post> response) { Post post = response.body(); textView.append(post.getId() + "\n"); textView.append(post.getUserId() + "\n"); textView.append(post.getTitle() + "\n"); textView.append(post.getBody() + "\n"); } @Override public void onFailure(@NonNull Call<Post> call, @NonNull Throwable t) { textView.append("Error occurred while getting request!"); t.printStackTrace(); } });
O objeto Call
retornado contém um método chamado enqueue
, que leva o Callback<T>
chamada Callback<T>
como parâmetro. No onResponse
, obtemos o resultado Response<Post>
contendo o objeto Post
retornado do servidor. Para obter o próprio objeto Post
, usamos o método response.body()
. O restante do código é compreensível sem mais explicações.
Enviando diferentes tipos de solicitações
A API JSONPlaceHolder
possui muitos pontos de extremidade diferentes que você pode usar.
Obtendo uma lista de mensagens
@GET("/posts") public Call<List<Post>> getAllPosts();
Para obter uma lista de todas as mensagens, alteramos o ponto final e o tipo de retorno da função.
Enviando solicitação com parâmetro
Se você deseja enviar uma solicitação com um parâmetro, basta usar a anotação @Query()
para o parâmetro correspondente no método:
@GET("/posts") public Call<List<Post>> getPostOfUser(@Query("userId") int id);
Portanto, se passarmos o valor 6 no parâmetro method, o terminal será o próximo - /posts?userId=6
.
Enviando uma solicitação POST
Para enviar uma solicitação POST, basta alterar a anotação do método.
@POST("/posts") public Call<Post> postData(@Body Post data);
Para formar o corpo da solicitação para esse método, usamos a anotação @Body
para o parâmetro passado. A @Body
usará o Gson para converter @Body
em JSON.
Existem vários tipos diferentes de consultas que você pode usar, mas este é um tópico para um artigo separado.
Solicitar interceptação
O Retrofit fornece uma maneira de interceptar solicitações e registrá-las no Logcat. Vamos montar um interceptador e ver essa mágica. Inclua a seguinte dependência no arquivo build.gradle
:
implementation 'com.squareup.okhttp3:logging-interceptor:3.8.0'
Atualize a classe NetworkService
seguinte maneira:
public class NetworkService { private static NetworkService mInstance; private static final String BASE_URL = "https://jsonplaceholder.typicode.com"; private Retrofit mRetrofit; private NetworkService() { HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor(); interceptor.setLevel(HttpLoggingInterceptor.Level.BODY); OkHttpClient.Builder client = new OkHttpClient.Builder() .addInterceptor(interceptor); mRetrofit = new Retrofit.Builder() .baseUrl(BASE_URL) .addConverterFactory(GsonConverterFactory.create()) .client(client.build()) .build(); } public static NetworkService getInstance() { if (mInstance == null) { mInstance = new NetworkService(); } return mInstance; } public JSONPlaceHolderApi getJSONApi() { return mRetrofit.create(JSONPlaceHolderApi.class); } }
Agora, quando você envia ou recebe uma solicitação, todos os seus dados, incluindo URLs, cabeçalhos, corpo, serão exibidos no log:
D/OkHttp: <-- 200 https://jsonplaceholder.typicode.com/posts/1 (3030ms) date: Tue, 24 Apr 2018 15:25:19 GMT content-type: application/json; charset=utf-8 set-cookie: __cfduid=d16d4221ddfba20b5464e6829eed4e3d11524583519; expires=Wed, 24-Apr-19 15:25:19 GMT; path=/; domain=.typicode.com; HttpOnly x-powered-by: Express vary: Origin, Accept-Encoding access-control-allow-credentials: true cache-control: public, max-age=14400 pragma: no-cache expires: Tue, 24 Apr 2018 19:25:19 GMT 04-24 15:25:16.204 7023-7056/com.thetehnocafe.gurleensethi.retrofitexample D/OkHttp: x-content-type-options: nosniff etag: W/"124-yiKdLzqO5gfBrJFrcdJ8Yq0LGnU" via: 1.1 vegur cf-cache-status: HIT expect-ct: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct" server: cloudflare cf-ray: 410994f328963066-SIN 04-24 15:25:16.246 7023-7056/com.thetehnocafe.gurleensethi.retrofitexample D/OkHttp: { 04-24 15:25:16.247 7023-7056/com.thetehnocafe.gurleensethi.retrofitexample D/OkHttp: "userId": 1, "id": 1, "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit", "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto" } <-- END HTTP (292-byte body)
Isso conclui nosso artigo. Você pode encontrar o código para este projeto no GitHub .