Flutter - Lista básica com ListView - IV
Hoje vamos continuar a apresentar como exibir uma lista de dados usando Flutter, desta vez obtendo os dados no formato JSON via Http. |
Continuando a terceira parte do artigo hoje veremos como obter dados de uma API REST no formato JSON via HTTP e exibir em um ListView criado usando o construtor ListView.builder.
Obtendos dados da internet no formato JSON
Obter dados da internet é uma tarefa comum hoje em dia, e o Flutter e o Dart permitem realizar essa tarefa de forma bem simples.
O roteiro básico a seguir é :
É isso que iremos fazer neste artigo.
Vamos exibir no ListView os dados obtidos no formato JSON a partir de uma API REST. Existem muitas serviços REST disponíveis que oferecem serviços para obter dados.
Neste artigo vamos usar os dados disponível neste endpoint: https://unsplash.com/napi/photos/Q14J2k8VE3U/related
Abaixo temos os dados no formato JSON retornados por esta url:
{ "total":20, "results":[ { "id":"hzgs56Ze49s", "created_at":"2015-04-25T07:52:00-04:00", "updated_at":"2019-04-21T19:55:18-04:00", "width":5616, "height":3744, "color":"#876B59", "description":"party fans raised their hands", "alt_description":"person performing heart hand gesture", "urls":{ "raw":"https://images.unsplash.com/photo-1429962714451-bb934ecdc4ec?ixlib=rb-1.2.1", "full":"https://images.unsplash.com/photo-1429962714451-bb934ecdc4ec?ixlib=rb-1.2.1&q=85&fm=jpg&crop=entropy&cs=srgb", "regular":"https://images.unsplash.com/photo-1429962714451-bb934ecdc4ec?ixlib=rb-1.2.1&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=1080&fit=max", "small":"https://images.unsplash.com/photo-1429962714451-bb934ecdc4ec?ixlib=rb-1.2.1&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=400&fit=max", "thumb":"https://images.unsplash.com/photo-1429962714451-bb934ecdc4ec?ixlib=rb-1.2.1&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=200&fit=max" }, "links":{ "self":"https://api.unsplash.com/photos/hzgs56Ze49s", "html":"https://unsplash.com/photos/hzgs56Ze49s", "download":"https://unsplash.com/photos/hzgs56Ze49s/download", "download_location":"https://api.unsplash.com/photos/hzgs56Ze49s/download" }, "categories":[
],
], |
Vamos obter os dados das urls das imagens, descrição e likes, de forma que nosso ListView vai exibir em uma coluna a imagem, e, em uma linha vai exibir a descrição e a quantidade de likes.
Nota: Se você quiser obter os objetos Dart a partir do formato JSON pode utilizar este link: https://javiercbk.github.io/json_to_dart/
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_json 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.
Como podemos acessar dados via HTTP no Flutter ?
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.
O código usado para obter dados via Http é dado a seguir:
Future<String> getJSONData() async {
var response = await http.get(
Uri.encodeFull("https://unsplash.com/napi/photos/Q14J2k8VE3U/related"),
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 do futuro será Future<void>.
Quando uma função que retorna um futuro é 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.
Exibindo Imagens no ListView
Como vamos exibir imagens, para obter desempenho, vamos usar imagens em cache.
Segundo a documentação temos que usar o pacote cached_network_image 0.7.0 que usa construtores para o placeholder e o widget de erro e usa o sqflite para o gerenciamento de cache.
Para isso vamos incluir no arquivo pubspec.yaml a referência ao pacote cached_network_image 0.7.0 conforme abaixo:
Teremos também que importar o pacote : import 'package:cached_network_image/cached_network_image.dart'; no arquivo main.dart.
Definindo o código do projeto
Abra o arquivo main.dart na pasta lib e defina os seguintes imports:
import
'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'package:cached_network_image/cached_network_image.dart';
O primeiro implementa o material design, o segundo permite realizar requisições http, o terceiro permite codificar e decodificar o JSON e o último permite trabalhar com imagens no cache.
A seguir defina o ponto de entrada da aplicação no método main() e o código do widget MyApp que estende de StatelessWidget:
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'ListView - Http e Json'),
);
}
}
|
Agora precisamos incluir o código da classe MyHomePage() onde definimos a classe privada _MyHomePageState que sobrescreve o método createState():
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
|
Na classe _MyHomePageState() obtemos os dados no formato JSON e invocamos o widget _criaListView():
class _MyHomePageState extends State<MyHomePage> {
List data;
// Função para obter os dados JSON
Future<String> getJSONData() async {
var response = await http.get(
// codifiga a url
Uri.encodeFull("https://unsplash.com/napi/photos/Q14J2k8VE3U/related"),
// Aceita somente resposta JSON
headers: {"Accept": "application/json"}
);
setState(() {
// Pega os dados JSON
data = json.decode(response.body)['results'];
});
return "Dados obtidos com sucesso";
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: _criaListView(),
);
}
|
O widget _criaListaView cria um listview usando o construtor ListView.builder e invoca o widget _criaImagemColuna() passando os dados para exibição:
Widget _criaListView() {
return ListView.builder(
padding: const EdgeInsets.all(16.0),
itemCount: data == null ? 0 : data.length,
itemBuilder: (context, index) {
return _criaImagemColuna(data[index]);
}
);
}
|
O widget _criaImagemColuna define um contâiner e um boxdecoration e tem como filho uma coluna onde vai exibir a imagem usando cache, depois invoca o widget _criaLinha passando os dados para exibir:
Widget _criaImagemColuna(dynamic item) => Container(
decoration: BoxDecoration(
color: Colors.white54
),
margin: const EdgeInsets.all(4),
child: Column(
children: [
new CachedNetworkImage(
imageUrl: item['urls']['small'],
placeholder: (context, url) => new CircularProgressIndicator(),
errorWidget: (context, url, error) => new Icon(Icons.error),
fadeOutDuration: new Duration(seconds: 1),
fadeInDuration: new Duration(seconds: 3),
),
_criaLinha(item)
],
),
);
|
O widget _criaLinha define um ListTile no ListView e exibe a descrição e a quantidade de likes:
Widget _criaLinha(dynamic item) {
return ListTile(
title: Text(
item['description'] == null ? '': item['description'],
),
subtitle: Text("Likes: " + item['likes'].toString()),
);
}
@override
void initState() {
super.initState();
// Chama o método getJSONData() quando a app inicializa
this.getJSONData();
}
}
|
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:
Vemos assim os dados obtidos via http no formato JSON sendo exibidos no ListView.
Pegue o projeto do arquivo main.dart aqui: main_dart.zip
"Palavra fiel
é esta: que, se morrermos com ele, também com ele viveremos;
Se sofrermos, também com ele reinaremos; se o negarmos, também ele nos negará;
Se formos infiéis, ele permanece fiel; não pode negar-se a si mesmo."
2 Timóteo 2:11-13
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 - Apresentando o widget MaterialApp - Macoratti
Flutter - Apresentando Flutter Studio - Macoratti
Flutter - Lista Básica - Macoratti
Flutter - Apresentando Widgets - Macoratti
Flutter - Obtendo dados da Web - Macoratti