Flutter - Consumindo API
Afluentes: Dispositivos Móveis; Usabilidade, desenvolvimento web, mobile e jogos
Pré-requisitos
Primeiro vamos criar nosso projeto e incluir alguns pacotes, então digite na pasta do projeto:
flutter create movies cd movies flutter pub add url_launcher flutter pub add flutter_linkify flutter pub add http
Código
O Aplicativo faz uma requisição de filmes em uma API. Tal como fizemos no Consumindo API com React.js, só que agora em Flutter.
O arquivo main.dart é simples e ele só inicia a página principal.
main.dart
1import 'package:flutter/material.dart';
2import 'movies.dart';
3
4void main() => runApp(const App());
5
6class App extends StatelessWidget {
7 const App({super.key});
8
9 @override
10 build(context) {
11 return const MaterialApp(
12 title: 'Filmes',
13 home: MoviesListView(),
14 );
15 }
16}
api.dart
O arquivo api.dart faz referência à API TVMaze e gerencia o objeto de transferência de um filme.
1import 'package:http/http.dart' as http;
2
3// A URL da API
4const baseUrl = "https://api.tvmaze.com/search/shows?q=";
5
6// Criamos a classe da nossa API. O nome você que escolhe. Fazemos aqui
7// uma requisição get (como fizemos no react) e passamos a URL, mas usamos
8// um Uri.parse pra transformar a string em uma URI.
9class API {
10 static Future getMovie(search) async {
11 var url = baseUrl + search;
12 return await http.get(Uri.parse(url));
13 }
14}
15
16// Criamos uma classe para representar os objetos que vão conter os filmes
17// e colocamos só os campos que vamos usar.
18class Movie {
19 int id;
20 String name;
21 String link;
22 String image;
23
24 Movie(this.id, this.name, this.link, this.image);
25
26 Movie.fromJson(Map json)
27 : id = json['show']['id'],
28 name = json['show']['name'],
29 link = json['show']['url'],
30 image = json['show']['image']['medium'];
31}
movies.dart
O arquivo movie.dart conteém a lista de filmes no formato JSON que ele vai trazer da API e cria uma LIST com objetos do tipo Movie criado no arquivo api.dart.
1import 'package:flutter/material.dart';
2import 'dart:convert';
3import 'api.dart';
4import 'detail.dart';
5
6// Vamos precisar de uma aplicação com estado
7class MoviesListView extends StatefulWidget {
8 const MoviesListView({super.key});
9
10 @override
11 State<MoviesListView> createState() => _MoviesListViewState();
12}
13
14class _MoviesListViewState extends State<MoviesListView> {
15 List<Movie> movies = List<Movie>.empty(); // Lista dos filmes
16 String search = "star%20trek"; // Plavra chave da pesquisa
17
18 // Construtor, atualiza com setState a lista de filmes.
19 _MoviesListViewState() {
20 API.getMovie(search).then((response) {
21 setState(() {
22 Iterable lista = json.decode(response.body); // Usamos um iterator
23 movies = lista.map((model) => Movie.fromJson(model)).toList();
24 });
25 });
26 }
27
28 // Método build sobrecarregado que vai construir nossa página
29 @override
30 Widget build(BuildContext context) {
31 return Scaffold(
32 appBar: AppBar(
33 title: const Text("Lista de Filmes"),
34 ),
35 // Aqui vem nossa lista
36 body: ListView.builder(
37 itemCount: movies.length, // quantidade de elementos
38 // Os elementos da lista
39 itemBuilder: (context, index) {
40 // Vai ser um item de lista tipo ListTile
41 return ListTile(
42 // Uma imagem de avatar redondinho com a imagem do filme
43 leading: CircleAvatar(
44 backgroundImage: NetworkImage(
45 movies[index].image,
46 ),
47 ),
48 // No título é o nome do filme
49 title: Text(
50 movies[index].name,
51 style: const TextStyle(
52 fontSize: 20.0,
53 color: Colors.black,
54 ),
55 ),
56 // No subtítulo colocamos o link
57 subtitle: Text(movies[index].link),
58 // Ação de clicar
59 onTap: () {
60 // Abrimos uma nova página, outra classe, que está no arquivo
61 // detail.dart. Veja que é um MaterialPageRote, tipo o
62 // MaterialApp, só que é só uma página nova.
63 Navigator.push(
64 context,
65 MaterialPageRoute(
66 builder: (context) => DetailPage(movies[index]),
67 ),
68 );
69 },
70 );
71 },
72 ),
73 );
74 }
75}
details.dart
Esse arquivo contém a página que é chamada para mostrar detalhes de um filme depois que você clicar nele na lista de filmes de movies.dart.
1import 'package:flutter/material.dart';
2import 'package:url_launcher/url_launcher.dart';
3import 'package:flutter_linkify/flutter_linkify.dart';
4import 'api.dart';
5
6// Uma página para mostrar os detalhes de cada filme. Passamos o objeto
7// do filme como parâmetro no constructor
8class DetailPage extends StatelessWidget {
9 final Movie movie;
10
11 const DetailPage(this.movie, {super.key});
12
13 @override
14 Widget build(BuildContext context) {
15 return Scaffold(
16 appBar: AppBar(
17 title: Text(movie.name),
18 ),
19 body: Container(
20 padding: const EdgeInsets.all(10.0),
21 child: Column(
22 children: [
23 Center(
24 child: Image(
25 image: NetworkImage(
26 movie.image,
27 ),
28 ),
29 ),
30 const Text("Link:"),
31 // Aqui a gente coloca um link clicável.
32 Linkify(
33 onOpen: (link) async {
34 if (await canLaunch(movie.link)) {
35 await launch(movie.link);
36 } else {
37 throw 'Não foi possível abrir {$movie.link}';
38 }
39 },
40 text: movie.link,
41 ),
42 ],
43 ),
44 ),
45 );
46 }
47}
Atividades
Desafio 1
1. Implemente o exemplo anterior em seu comptuador.
Desafio 2
Implemente uma aplicação que consuma alguma outra API de sua escolha. Se você já estiver trabalhando com criação de microsserviços web na disciplina de Sistemas Distribuídos, você pode criar uma API pra consumir no flutter.