Flutter - Entendendo FutureBuilder - III


 Hoje vamos continuar usando FutureBuilder para obter dados da web e exibir no ListView.

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

Usando FutureBuilder na prática

Vamos continuar o artigo anterior, e, agora vamos usar o FutureBuilder mostrando como obter dados remotos.

Vamos iniciar definindo o layout padrão usando o MaterialApp e o Scaffold usando um StatefulWidget:

import 'package:flutter/material.dart';
void main() {
  runApp(
    MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Home(),
    ),
  );
}
class Home extends StatefulWidget {
  @override
  _HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {  
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("FutureBuilder")
       ),
       body: Text("teste") 
      );
    }
}

Precisamos definir uma fonte de dados remota que será acessada para retornar os dados que iremos exibir.

Vamos usar o serviço gratuito disponibilizado pelo site: https://jsonplaceholder.typicode.com/posts/

que retorna dados no formato JSON que podemos usar.

Para acessar dados da internet vamos precisar usar o pacote http e realizar as seguintes taraefas:

  1. Incluir o pacote http no projeto
  2. Fazer uma requisição para uma url usando o pacote http
  3. converter a resposta obtida em um objeto Dart
  4. Tratar e exibir os dados no Flutter

Para instalar o pacote http, adicione-o à seção de dependências do arquivo pubspec.yaml. Você pode encontrar a versão mais recente do pacote http no site do Pub.


 dependencies:
   http: <latest_version>

Para fazer a requisição no site JSONPlaceholder vamos usar o método get do pacote http.


 Future<http.Response> getDataPost() {
     return http.get(url);
}

O método http.get() retorna um Future que contém uma resposta e a classe http.Response contém os dados recebidos de uma chamada http bem-sucedida.

A seguir precisamos converter a resposta obtida para um objeto Dart que no exemplo deve ser a classe Post cuja estrutura vemos a seguir:

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 podemos converter o http.Response para um objeto Post e retornar um Future<Post>, para isso temos que :

  1. Converter o body do Response em um Mapa JSON com o pacote dart:convert.
  2. Se o servidor retornar uma resposta “OK” com um código de status de 200, temos que converter o Mapa JSON em um Post usando o método factory fromJson();
  3. Se o servidor retornar uma resposta inesperada, temos que enviar um erro;

Assim nossa função getDataPost() deve ficar assim:

Future<Post> getDataPost() async {

  final response =   await http.get(url);
  if (response.statusCode == 200) {
    return Post.fromJson(json.decode(response.body));
  } else {
    throw Exception('Falha ao carregar dados...');
  }
}

Temos então que incluir uma referência no projeto ao  dart:convert :  import 'dart:convert';

Finalmente basta agora tratar e exibir os dados.

Para buscar os dados e exibi-los na tela, vamos usar FutureBuilder fornecendo dois parâmetros:

  1. future - Representa os dados com que vamos tratar, no exemplo vamos usar getDataPost();
  2. builder - É uma função de construtor que informa ao Flutter o que processar, dependendo do estado do Future: carregamento, sucesso ou erro.
FutureBuilder<Post>(
  future: fetchPost(),
  builder: (context, snapshot) {

    if (snapshot.hasData) {
      return Text(snapshot.data.title);
    } else if (snapshot.hasError) {
      return Text("${snapshot.error}");
    }
    return CircularProgressIndicator();
  },
);

Aqui snapshot representa um instantâneo dos dados recebidos.

Assim o código completo do arquivo main.dart ficou assim:

import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter_conversor/post.dart';
import 'package:http/http.dart' as http;
const url = "https://jsonplaceholder.typicode.com/posts/1";
void main() async {
  runApp(MaterialApp(
    home: Home( 
    ),
  ));
}

class Home extends StatefulWidget {
  @override
  _HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("FutureBuilder")
       ),
       body: buildFutureBuilder()
      );
    }
  buildFutureBuilder() {
    return FutureBuilder<Post>(
       future : getDataPost(),
       builder: (context, snapshot) {
          switch(snapshot.connectionState){
            case ConnectionState.none :
            case ConnectionState.waiting:
            return Center(
              child: Text("Carregando...")
             );
             default: 
             if(snapshot.hasError){
               return Center(
                 child: Text("Erro ao carregar..."),   
                );
           } else {
             return Center(
               child: 
               Text(snapshot.data.title));
           }
         }
       });
  }   
    Future<Post> getDataPost() async {

      final response =   await http.get(url);    
      if (response.statusCode == 200) {
        return Post.fromJson(json.decode(response.body));
      } else {
        throw Exception('Falha ao carregar dados...');
      }
    }
}

Estamos exibindo apenas o valor de title usando um widget Text centralizado.

Essa abordagem para usar o FutureBuilder embora funcione não é a mais recomendada. Em outro artigo veremos como otimizar o código para usar o FutureBuilder de forma correta.

"Bem-aventurado o homem que não anda segundo o conselho dos ímpios, nem se detém no caminho dos pecadores, nem se assenta na roda dos escarnecedores.
Antes tem o seu prazer na lei do Senhor, e na sua lei medita de dia e de noite."

Salmos 1:1,2

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:


José Carlos Macoratti