Retrofit — A maneira mais fácil de chamar APIs Rest no Flutter

Tempo de leitura: 4 minutes

Flutter contém módulos de Networking e JSON serialization. Para os pequenos dados JSON, ainda precisamos escrever muito mais código clichê, pois o Dart não oferece suporte à reflexão (o Gson o usa).

Se você trabalhou em Android ou iOS, talvez já tenha usado bibliotecas como Retrofit e Alamofire. Como usamos chamadas de API Rest em quase todos os aplicativos, elas agora são uma parte crucial do funcionamento do aplicativo. Essas bibliotecas cuidam de toda a análise de dados e isso torna a API chamada moleza.

Neste post, vamos aprender como usar a biblioteca Retrofit no Flutter.

Para chamar APIs Rest enviando cabeçalhos dinâmicos, parâmetros, solicitação e resposta de maneira personalizada e segura, “Retrofit” é a melhor maneira.

Vamos sujar as mãos!! 🙌🏻 😄

Etapa 1: criar um aplicativo Flutter

Etapa 2: Para trabalhar com a implementação do Retrofit no flutter, precisamos adicionar as dependências abaixo no arquivo pubspec.yaml.

dependencies:
  retrofit: ^4.0.1
  dio: ^4.0.6
  built_value: ^8.4.4
  json_annotation: ^4.8.0

dev_dependencies:
  retrofit_generator: ^6.0.0+2
  build_runner: ^2.3.3
  json_serializable: ^6.6.1
  built_value_generator: ^8.4.4

Dio é nosso cliente Http e cuida da conexão para nós.
Retrofit é um cliente Dio que facilita o consumo de APIs Rest.
Build runner é usado para geração de código no Dart, além do pub.
JSON Serialization cria uma classe de modelo a partir de dados JSON.

 

Etapa 3: Para demonstrar a chamada de API neste exemplo, usaremos esta API pública: https://gorest.co.in/public-api/users

Vamos criar uma classe abstrata ApiRequest & APIs

///APIs class is for api tags
class Apis {
  static const String users = '/users';
}
@RestApi(baseUrl: "https://gorest.co.in/public-api/")
abstract class ApiClient {
  factory ApiClient(Dio dio, {String baseUrl}) = _ApiClient;

  @GET(Apis.users)
  Future<ResponseData> getUsers();
}

A classe ApiClient é responsável por lidar com todos os métodos de chamada de rede. No código acima, apresentará um erro na variável _ApiClient, que será resolvido com os passos que veremos mais adiante neste post.

As anotações no método e no parâmetro de URL decidem como a solicitação será tratada. Todo método deve ter anotação HTTP e parâmetros relativos. Existem algumas anotações internas como GET, PUT, POST, PATCH, DELETE & HEADER. Adicione métodos com anotações no ApiClient como acima.

Aqui está um exemplo com diferentes anotações. (Pode não corresponder ao baseURL.)

//Dynamic headers
@GET("/posts")
Future<List<Post>> getPosts(@Header("Content-Type") String contentType );
@GET("/comments")
@Headers(<String, dynamic>{ //Static header
  "Content-Type" : "application/json",
  "Custom-Header" : "Your header"
})
Future<List<Comment>> getAllComments();
@GET("/posts/{id}")
Future<Post> getPostFromId(@Path("id") int postId);
@GET("/comments?postId={id}")
Future<Comment> getCommentFromPostId(@Path("id") int postId);
@GET("/comments")
Future<Comment> getCommentFromPostIdWithQuery(@Query("postId") int postId); //This yields to "/comments?postId=postId
@DELETE("/posts/{id}")
Future<void> deletePost(@Path("id") int postId);
@POST("/posts")
Future<Post> createPost(@Body() Post post);

Parâmetros do método:

@Path– Para atualizar a URL dinamicamente, o bloco de substituição entre { } deve ser anotado com @Path usando a mesma string.
@Body– Envia o objeto de dardo como o corpo da solicitação.
@Query– usado para anexar o URL.
@Headers– para passar os cabeçalhos dinamicamente.

Para resolver o erro precisamos adicionar a parte ‘api_client.g.dart’; na declaração de importação. Ele mostrará o aviso “Missing “part ‘api_client.g.dart’;
Execute o comando: flutter pub run build_runner build

O arquivo de peça permite dividir um arquivo em vários arquivos dart.

O comando acima irá gerar o arquivo api_client.g.dart e contém todos os dados sobre a criação da instância do Retrofit e a busca de dados da rede.

Se você fez alguma alteração no ApiClient, execute também o comando para atualizar o arquivo de peça ou execute commend flutter pub run build_runner watch as alterações nos arquivos do projeto e crie automaticamente os arquivos sempre que necessário. É seguro iniciar o observador uma vez e deixá-lo rodando em segundo plano.

 

Etapa 4: criar classes de dados

Nossa API retornará uma lista de usuários. Adicionando uma amostra de dados de API
{
  code: 200,
  meta: {
    pagination: {
      total: 1676,
      pages: 84,
      page: 1,
      limit: 20
    }
  },
  data: [
    {
      id: 1,
      name: "Mrs. Somnath Namboothiri",
      email: "somnath_namboothiri_mrs@baumbach-nitzsche.com",
      gender: "Female",
      status: "Active",
      created_at: "2020–08–31T03:50:04.198+05:30",
      updated_at: "2020–08–31T03:50:04.198+05:30"
    },
    
  ]
}

Vamos criar um data.dart e adicionar o código abaixo.

Existem duas maneiras de analisar o JSON.

I) Serialização Manual: Estamos recebendo uma resposta da API no formato JSON que temos que converter em classe dart.

class User {
  int id;
  String name;
  String email;
  String gender;
  String status;
  String created_at;
  String updated_at;

  User({this.id, this.name, this.email,this.gender, this.status, this.created_at, this.updated_at});

  factory User.fromJson(Map<String, dynamic> json) {
    return User(
      id: json['id'],
      name: json['name'],
      email: json['email'],
      gender: json['gender'],
      status: json['status'],
      created_at: json['created_at'],
      updated_at: json['updated_at'],
    );
  }

  Map<String, dynamic> toJson() {
    return {
      'id': id,
      'name': name,
      'email': email,
      'gender': gender,
      'status': status,
      'created_at': created_at,
      'updated_at': updated_at,
    };
  }
}

II) Serialização Automática: O Retrofit converte automaticamente a resposta “JSON” para a classe “User” no dart usando a classe User do JSON.

O código abaixo fará a serialização automática dos dados JSON.

Nesse momento, ele mostrará erros. Então vamos rodar o comando abaixo novamente e gerar a parte ‘data.g.dart’;
Execute o comando: flutter pub run build_runner build

import 'package:json_annotation/json_annotation.dart';
part 'data.g.dart';

@JsonSerializable()
class User{
  int id;
  String name;
  String email;
  String gender;
  String status;
  String created_at;
  String updated_at;

  User({this.id, this.name, this.email,this.gender, this.status, this.created_at, this.updated_at});

  factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
  Map<String, dynamic> toJson() => _$UserToJson(this);
}

@JsonSerializable()
class ResponseData{
  int code;
  dynamic meta;
  List<dynamic>data;
  ResponseData({this.code, this.meta, this.data});
  factory ResponseData.fromJson(Map<String, dynamic> json) => _$ResponseDataFromJson(json);
  Map<String, dynamic> toJson() => _$ResponseDataToJson(this);
}

Essa abordagem de serialização é melhor para projetos de médio a grande porte, pois não precisamos de código clichê manuscrito. A desvantagem dessa abordagem é que precisamos de uma configuração inicial e, também, para cada classe de dardo, é criado um arquivo de peça que pode produzir desordem visual no projeto.

 

Etapa 5: vamos chamar a API com o objeto retrofit

FutureBuilder<ResponseData> _buildBody(BuildContext context) {
  final client = ApiClient(Dio(BaseOptions(contentType: "application/json")));
  return FutureBuilder<ResponseData>(
    future: client.getUsers(),
    builder: (context, snapshot) {
      if (snapshot.connectionState == ConnectionState.done) {

        final ResponseData posts = snapshot.data;
        return _buildListView(context, posts);
      } else {
        return Center(
          child: CircularProgressIndicator(),
        );
      }
    },
  );
}

Codificação feliz !! 🙂

Criei uma demonstração usando as dependências e etapas acima em um flutter.

Você pode encontrar o código-fonte deste post no seguinte repositório do Github:
https://github.com/caneto/flutter_retrofit

Há muito o que explorar com o Flutter, o seguinte link para o site oficial tem muito material útil relacionado a chamadas de API, que vale a pena dar uma olhada.

https://flutter.dev/docs/development/data-and-backend/json

Gostei muito de construir Listview usando chamada de API de retrofit com Flutter, pois permite chamar APIs enquanto escreve muito poucas linhas de código. Continuarei explorando diferentes estruturas e bibliotecas do Flutter,

Por favor, dê alguns 👏 se você gosta do que lê e siga-nos para se manter atualizado com nossas últimas postagens.