Skip to content

GitLab

  • Menu
Projects Groups Snippets
    • Loading...
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
    • Contribute to GitLab
  • Sign in
  • A Apus Drones Wiki
  • Project information
    • Project information
    • Activity
    • Labels
    • Planning hierarchy
    • Members
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
  • Issues 0
    • Issues 0
    • List
    • Boards
    • Service Desk
    • Milestones
  • Merge requests 0
    • Merge requests 0
  • CI/CD
    • CI/CD
    • Pipelines
    • Jobs
    • Schedules
  • Deployments
    • Deployments
    • Environments
    • Releases
  • Monitor
    • Monitor
    • Incidents
  • Analytics
    • Analytics
    • Value stream
    • CI/CD
    • Repository
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
Collapse sidebar
  • Apus Drones
  • Apus Drones Wiki
  • Wiki
  • Consumindo REST APIs no Flutter

Consumindo REST APIs no Flutter · Changes

Page history
Create Consumindo REST APIs no Flutter authored Sep 16, 2021 by Angelo Calebe Araujo da Rocha's avatar Angelo Calebe Araujo da Rocha
Hide whitespace changes
Inline Side-by-side
Consumindo-REST-APIs-no-Flutter.md 0 → 100644
View page @ d9fefa13
# Consumindo REST APIs no Flutter
## Requisições HTTP para REST APIs
Para chamar APIs, utilizamos o pacote `http`. Este pacote já está instalado no projeto, mas caso queira instalar em outro projeto:
- Execute o comando `flutter pub add http`;
- (Para projetos Android) No arquivo `AndroidManifest.xml`, adicione a permissão para acesso à Internet: `<uses-permission android:name="android.permission.INTERNET" />
`.
Para cada verbo, há um método associado (`http.get()`, `http.post()`, etc.). Esses métodos retornam um `Future` contendo um `http.Response`. `Future` é uma classe utilizada para operações assíncronas, como é o caso de requisições HTTP, e representa um potencial valor ou erro que será retornado em algum momento no futuro. `http.Response` é uma classe utilizada para armazenar o retorno de uma requisição.
_Os códigos a seguir podem ser executados diretamente no DartPad (https://dartpad.dev)_.
```
import 'package:http/http.dart' as http;
Future<http.Response> fetchUsers() {
return http.get(Uri.parse('https://jsonplaceholder.typicode.com/users'));
}
void users() async {
http.Response response = await fetchUsers();
String jsonBody = response.body;
print(jsonBody);
}
void main() {
users();
}
```
Com isso, já temos "em mãos" o retorno, porém em um formato "bruto" em uma String. No caso da API de nosso projeto, essa String contém um JSON.
Podemos decodificar o JSON utilizando um pacote nativo do Dart chamado `dart:convert`. Este pacote expõe um método `jsonDecode`, que utilizaremos a seguir:
```
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<http.Response> fetchUsers() {
return http.get(Uri.parse('https://jsonplaceholder.typicode.com/users'));
}
Future<http.Response> fetchUser(int id) {
return http.get(Uri.parse('https://jsonplaceholder.typicode.com/users/$id'));
}
void users() async {
http.Response response = await fetchUsers();
List<dynamic> users = jsonDecode(response.body);
print(users);
}
void user() async {
http.Response response = await fetchUser(1);
Map<String, dynamic> user = jsonDecode(response.body);
print(user);
}
void main() {
users();
user();
}
```
Como o JSON contém essencialmente apenas dados no formato `chave: valor` ou listas de chaves e valores, os retornos do método `jsonDecode` podem ser `Map<String, dynamic>` ou `List<dynamic>`, dependendo do caso (ou simplesmente `var` se estiver com preguiça).
## Convertendo de JSON para modelos e vice-versa
Como vimos anteriormente, é fácil de obter dados de API. Porém, não há ferramentas nativas para serialização e desserialização automática de classes modelo. Essa operação deve ser feita manualmente, o que pode ser trabalhoso e propenso a erros.
O código a seguir possui duas classes, que idealmente devem ser inseridas em arquivos diferentes, porém no formato atual pode ser executada no DartPad.
```
import 'dart:convert';
// Item.dart
class Item {
final String description;
Item({required this.description});
@override
String toString() {
return 'Item (description = ${this.description})';
}
factory Item.fromJson(Map<String, dynamic> json) {
return Item(description: json['description']);
}
Map<String, dynamic> toJson(Item item) =>
<String, dynamic>{'description': item.description};
}
// Person.dart
// import 'Item.dart';
class Person {
final String name;
final DateTime dob;
final num height;
final num weight;
final List<Item> items;
@override
String toString() {
return 'Person (name = ${this.name}, dob = ${this.dob}, height = ${this.height}, weight = ${this.weight}, items = ${this.items})';
}
Person({
required this.name,
required this.dob,
required this.height,
required this.weight,
required this.items,
});
factory Person.fromJson(Map<String, dynamic> json) {
return Person(
name: json['name'],
dob: DateTime.parse(json['dob'] as String),
height: json['height'],
weight: json['weight'],
items: (json['items'] as List<dynamic>)
.map((e) => Item.fromJson(e as Map<String, dynamic>))
.toList(),
);
}
Map<String, dynamic> toJson(Person person) => <String, dynamic>{
'name': person.name,
'dob': person.dob,
'height': person.height,
'weight': person.weight,
};
}
void person() async {
Map<String, dynamic> person = jsonDecode('{"name": "Uncle Bob", "dob": "1980-02-28", "height": 1.8, "weight": 75.6, "items": [{"description": "Wooden sword"}, {"description": "Vibranium shield"}]}');
print(person);
Person model = Person.fromJson(person);
print(model);
}
void main() {
person();
}
```
Para facilitar o desenvolvimento, utilizaremos os pacotes `json_annotation`, `json_serializable` e `build_tools`. Estes pacotes já estão instalados no projeto, mas, se quiser instalá-los, execute os seguintes comandos:
```
flutter pub add json_annotation
flutter pub add -d json_serializable build_tools
```
Agora, podemos criar as classes da seguinte forma:
```
// Item.dart
import 'package:json_annotation/json_annotation.dart';
part 'Item.g.dart';
@JsonSerializable()
class Item {
final String description;
Item({required this.description});
factory Item.fromJson(Map<String, dynamic> json) => _$ItemFromJson(json);
Map<String, dynamic> toJson() => _$ItemToJson(this);
}
```
```
// Person.dart
import 'package:json_annotation/json_annotation.dart';
part 'Person.g.dart';
@JsonSerializable()
class Person {
final String name;
final DateTime dob;
final num height;
final num weight;
final List<Item> items;
Person({
required this.name,
required this.dob,
required this.height,
required this.weight,
required this.items,
});
factory Person.fromJson(Map<String, dynamic> json) => _$PersonFromJson(json);
Map<String, dynamic> toJson() => _$PersonToJson(this);
}
```
A linha que contém `part '[Classe].g.dart` referencia um arquivo que ainda não existe e será gerado automaticamente. Para isso, é necessário iniciar um processo, que ficará executando em background, monitorando o código. Execute o seguinte comando:
```
flutter pub run build_runner watch
```
Ao iniciar o processo, os arquivos `*.g.dart` serão criados. Se alguma classe for modificada, esses arquivos serão atualizados automaticamente, desde que o processo esteja em execução. Por isso, é recomendável reservar uma janela de terminal para ele.
É possível que o processo encontre erros e feche. Nesse caso, o erro deve ser corrigido e o processo executado novamente.
Caso ocorra um erro iniciando com `Conflicting outputs were detected and the build is unable to prompt for permission to remove them. These outputs must be removed manually or the build can be run with ``--delete-conflicting-outputs``.`, delete todos os arquivos *.g.dart e execute o processo novamente.
Ainda há bastante código para escrever ao criar uma classe. Para facilitar, existe uma extensão do VSCode chamada _Flutter Helpers_ (https://marketplace.visualstudio.com/items?itemName=aksharpatel47.vscode-flutter-helper). Esta extensão possui 2 snippets (`jsf` e `jsc`) e 2 comandos para executar o processo que gera os arquivos `*.g.dart` (um para executar uma vez e outro para iniciar o monitoramento).
| ![Criando um modelo](http://tools.ages.pucrs.br/apus-drones/apus-drones-wiki/raw/master/tutorials/flutter_json_1.gif) |
|:--:|
| *Criando um modelo* |
| ![Alterando um modelo](http://tools.ages.pucrs.br/apus-drones/apus-drones-wiki/raw/master/tutorials/flutter_json_2.gif) |
|:--:|
| *Alterando um modelo* |
## Referências
- flutter.dev - Fetch data from the internet: https://flutter.dev/docs/cookbook/networking/fetch-data
- flutter.dev - JSON and serialization: https://flutter.dev/docs/development/data-and-backend/json
- pub.dev - Response class: https://pub.dev/documentation/http/latest/http/Response-class.html
- api.flutter.dev - Future\<T\> class: https://api.flutter.dev/flutter/dart-async/Future-class.html
Clone repository
  • Consumindo REST APIs no Flutter
  • Utilizando a wiki
    • adicionando imagens
    • escrevendo em markdown
    • wiki no editor de texto
  • arquitetura
  • banco_dados
  • codigo
  • configuracao
  • design_mockups
  • escopo
  • Home
  • instrucoes
  • processo
  • qualidade
  • utilizacao