Flutter - Obtendo dados da Web (REST)
Hoje veremos como podemos obter dados da internet e exibí-los em aplicações Flutter. |
O Flutter é um SDK de aplicativo móvel do Google que ajuda a criar aplicativos móveis modernos para iOS e Android usando uma única (quase) base de código.
Se você não conhece o Flutter veja o meu artigo : Flutter - Primeiros contatos e impressões
Obtendos dados da internet
Atualmente obter dados da internet é um requisito básico em muitas aplicações, e, o Flutter e o Dart nos fornecem ferramentas para realizar esse trabalho.
O roteiro básico a seguir é :
É isso que iremos fazer neste artigo a seguir mostrando como realizar cada uma das etapas acima.
Antes de iniciar precisamos definir qual a nossa fonte de dados, ou seja, qual a URL vamos acessar para obter dados.
Existem muitas opções, e , neste exemplo vou acessar a url : https://jsonplaceholder.typicode.com/posts que retorna dados no formato JSON conforme abaixo:
[ { "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" }, { "userId": 1, "id": 2, "title": "qui est esse", "body": "est rerum tempore vitae\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\nqui aperiam non debitis possimus qui neque nisi nulla" }, { "userId": 1, "id": 3, "title": "ea molestias quasi exercitationem repellat qui ipsa sit aut", "body": "et iusto sed quo iure\nvoluptatem occaecati omnis eligendi aut ad\nvoluptatem doloribus vel accusantium quis pariatur\nmolestiae porro eius odio et labore et velit aut" }, { ... ... ] |
Mais informações você obtém no site : https://jsonplaceholder.typicode.com/
Para a API que vamos usar os métodos HTTP disponíveis são:
GET | /posts |
GET | /posts/1 |
GET | /posts/1/comments |
GET | /comments?postId=1 |
GET | /posts?userId=1 |
POST | /posts |
PUT | /posts/1 |
PATCH | /posts/1 |
DELETE | /posts/1 |
Criando o projeto Flutter
Vamos começar criando o projeto flutter.
Eu estou usando o Flutter versão 1.2.1, e como editor de código estou usando o VS Code com o plugin Flutter instalado.
No Visual Studio Code tecle CTRL+ SHIFT+P para abrir a paleta de comandos e a seguir selecione a opção : Fluter:New Project
A seguir informe o nome do projeto : flutter_http_web e tecle ENTER.
Na janela de
diálogo a seguir, selecione a pasta onde o projeto vai ser salvo e clique em :
Select a folder to create the project in
O Flutter vai criar um projeto padrão onde todo o código da aplicação vai estar no arquivo main.dart dentro da pasta lib do projeto.
A seguir podemos abrir o projeto usando o VS Code usando a opção Open folder e escolhendo a pasta flutter_http_web.
1- Adicionar o pacote http
O pacote http
fornece a maneira mais simples de buscar dados da Internet.
Para instalar o pacote http, você deve adicioná-lo à seção de dependências do
arquivo pubspec.yaml do projeto Flutter. Você pode
encontrar a versão mais recente do pacote http neste
link.
Hoje, abril de 2019, a versão atual deste pacote é a versão : http 0.12.0+2
Conforme a documentação temos que usar o pacote http 0.12.0+2 que contém um conjunto de funções de alto nível que torna fácil consumir recursos HTTP. Sendo independente de plataforma e podendo ser usado na linha de comando e no browser.
Para isso vamos incluir no arquivo pubspec.yaml a referência ao pacote http: ^0.12.0.0+2 conforme abaixo:
Além disso vamos ter que importar o pacote : import 'package:http/http.dart'; no arquivo main.dart.
2- Fazer uma requisição web usando o pacote http
Já sabemos que vamos acessar a API REST disponível em JSONPlaceholder, assim, um exemplo de código fazendo uma requisição HTTP com o método Get() pode ser vista abaixo: (obtido da documentação)
Future<String> getJSONData() async { var response = await http.get( Uri.encodeFull("https://jsonplaceholder.typicode.com/posts/1"), headers: {"Accept": "application/json"} ); setState(() {
// otem os dados JSON
data = json.decode(response.body)['results'];
});
return "Dados obtidos com sucesso";
}
|
No código acima você pode estranhar o uso de Future.
O que é Future ?
Um
Future é um
objeto Future<T>, que representa uma operação
assíncrona que produz um resultado do tipo T. Se o resultado não for um valor
utilizável, o tipo Future será Future<void>.
Quando uma função que retorna um Future é invocada, duas coisas acontecem:
1- A função enfileira o trabalho a ser feito e retorna um objeto
Future não
concluído.
2- Posteriormente, quando a operação for concluída, o objeto
Future será
concluído com um valor ou com um erro.
E quando escrevemos código que depende de um Future podemos usar async e await.
A seguir definimos a url e o cabeçalho application/json e obtemos os dados atualizando o estado.
3- Converter a resposta em um objeto Dart personalizado
Embora seja fácil fazer uma requisição na web, trabalhar com Future<http.Response> não é muito conveniente. Para tornar nossa vida mais fácil, precisamos converter o http.Response em um objeto Dart.
A resposta da API REST quando acessarmos o endpoint terá o seguinte formato JSON:
{ "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" } |
Precisamos criar uma classe que represente o modelo de domínio para esta estrutura JSON.
Podemos fazer isso manualmente ou usar o recurso disponível neste site: https://app.quicktype.io/
Essa ferramenta criará suas classes de modelo, os métodos de fábrica e os métodos de conversão.
Abaixo temos o resultado final obtido para o formato JSON retornado pela API REST:
class Post {
final int userId;
final int id;
final String title;
final String body;
Post({this.userId, this.id, this.title, this.body});
factory Post.fromJson(Map<String, dynamic> json) {
return Post(
userId: json['userId'],
id: json['id'],
title: json['title'],
body: json['body'],
);
}
}
|
Agora, vamos definir um método fetchPost para retornar um Future<Post>.Para fazer isso, teremos que fazer o seguinte:
Abaixo temos o código do método fetchPost() :
Future<Post> fetchPost() async {
final response = await http.get('https://jsonplaceholder.typicode.com/posts/1');
if (response.statusCode == 200) {
// se o servidor retornar um response OK, vamos fazer o parse no JSON
return Post.fromJson(json.decode(response.body));
} else {
// se a responsta não for OK , lançamos um erro
throw Exception('Failed to load post');
}
}
|
Agora estamos obtendo os dados via get http do endpoint : https://jsonplaceholder.typicode.com/posts/1
4- Pegar e Exibir os dados com o Flutter;
Para buscar os
dados e exibi-los na tela, você pode usar o widget
FutureBuilder. Este Widget vem com o Flutter e facilita o trabalho com
fontes de dados assíncronas.
Você deve fornecer dois parâmetros:
A seguir vemos o código usando o widget FutureBuilder:
FutureBuilder<Post>(
future: fetchPost(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return Text('Id :' + snapshot.data.id.toString() + '\n\ntitle : ' +
snapshot.data.title + '\n\nbody : ' + snapshot.data.body);
} else if (snapshot.hasError) {
return Text("${snapshot.error}");
}
// exibe um spinner carregando
return CircularProgressIndicator();
},
);
|
Embora seja
conveniente, não é recomendável fazer uma chamada para uma API em um método
build().
O Flutter chama o método build() toda vez que ele
quer mudar alguma coisa na view, e isso acontece com frequência. Se fizermos a
chamada ao método que faz a requisição para o endpoint no
build(), iremos inundar a API com chamadas
desnecessárias impactando o desempenho da aplicação.
Podemos passar a chamada em um widget StateleslWidget onde o widget pai é responsável por chamar o método de fetchPost, armazenar seu resultado e, em seguida, transmiti-lo ao seu widget.
Para facilitar vamos colocar todo o código no arquivo main.dart. Veja como ficou o código completo:
import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
Future<Post> fetchPost() async {
final response = await http.get('https://jsonplaceholder.typicode.com/posts/2');
if (response.statusCode == 200) {
return Post.fromJson(json.decode(response.body));
} else {
throw Exception('Falha ao carregar um post');
}
}
class Post {
final int userId;
final int id;
final String title;
final String body;
Post({this.userId, this.id, this.title, this.body});
factory Post.fromJson(Map<String, dynamic> json) {
return Post(
userId: json['userId'],
id: json['id'],
title: json['title'],
body: json['body'],
);
}
}
void main() => runApp(MyApp(post: fetchPost()));
class MyApp extends StatelessWidget {
final Future<Post> post;
MyApp({Key key, this.post}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Obtendo dados da Web - Exemplo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
appBar: AppBar(
title: Text('Pegando dados da Web'),
),
body: Center(
child: FutureBuilder<Post>(
future: post,
builder: (context, snapshot) {
if (snapshot.hasData) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Text('Id :' + snapshot.data.id.toString() + '\n\ntitle : '
+ snapshot.data.title + '\n\nbody : ' + snapshot.data.body),
);
} else if (snapshot.hasError) {
return Text("${snapshot.error}");
}
return CircularProgressIndicator();
},
),
),
),
);
}
}
|
Para executar podemos pressionar F5 ou no terminal de comandos, estando posicionado na pasta do projeto, basta digitar : flutter run -d all
Executando o projeto iremos obter o resultado abaixo:
Dessa forma mostramos como fazer uma requisição http e consumir dados de uma API REST exibindo os dados em um Widget.
Pegue o projeto do arquivo main.dart aqui: main_dart_http.zip
"E, quanto
fizerdes por palavras ou por obras, fazei tudo em nome do Senhor Jesus, dando
por ele graças a Deus Pai."
Colossenses 3:17
Veja os
Destaques e novidades do SUPER DVD Visual Basic
(sempre atualizado) : clique e confira !
Quer migrar para o VB .NET ?
Quer aprender C# ??
Quer aprender os conceitos da Programação Orientada a objetos ? Quer aprender o gerar relatórios com o ReportViewer no VS 2013 ? |
Referências:
Super DVD Vídeo Aulas - Vídeo Aula sobre VB .NET, ASP .NET e C#
Super DVD C# - Recursos de aprendizagens e vídeo aulas para C#
Curso Fundamentos da Programação Orientada a Objetos com VB .NET
Flutter - Lista Básica - Macoratti
Flutter - Apresentando o widget MaterialApp - Macoratti
Flutter - Apresentando Flutter Studio - Macoratti
Flutter - Apresentando Widgets - Macoratti
Flutter - Criando uma tela de login - Macoratti