Mudanças entre as edições de "Flutter - Consumindo API"

De Aulas
 
Linha 207: Linha 207:
 
}
 
}
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
 +
= 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.

Edição das 09h09min de 30 de setembro de 2022

Afluentes: Dispositivos Móveis; Usabilidade, desenvolvimento web, mobile e jogos

Pré-requisitos

Primeiro vamos incluir alguns pacotes, então digite na pasta do projeto:

flutter pub pub add url_launcher
flutter pub pub add flutter_linkify
flutter pub 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(App());
 5
 6class App extends StatelessWidget {
 7  @override
 8  build(context) {
 9    return MaterialApp(
10      title: 'Filmes',
11      home: MoviesListView(),
12    );
13  }
14}

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(int id, String name, String link, String image) {
25    this.id = id;
26    this.name = name;
27    this.link = link;
28    this.image = image;
29  }
30
31  Movie.fromJson(Map json)
32      : id = json['show']['id'],
33        name = json['show']['name'],
34        link = json['show']['url'],
35        image = json['show']['image']['medium'];
36}

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  @override
 9  _MoviesListViewState createState() => _MoviesListViewState();
10}
11
12class _MoviesListViewState extends State<MoviesListView> {
13  List<Movie> movies = List<Movie>.empty(); // Lista dos filmes
14  String search = "star%20trek"; // Plavra chave da pesquisa
15
16  // Construtor, atualiza com setState a lista de filmes.
17  _MoviesListViewState() {
18    API.getMovie(search).then((response) {
19      setState(() {
20        Iterable lista = json.decode(response.body); // Usamos um iterator
21        movies = lista.map((model) => Movie.fromJson(model)).toList();
22      });
23    });
24  }
25
26  // Método build sobrecarregado que vai construir nossa página
27  @override
28  Widget build(BuildContext context) {
29    return Scaffold(
30      appBar: AppBar(
31        title: Text("Lista de Filmes"),
32      ),
33      // Aqui vem nossa lista
34      body: ListView.builder(
35        itemCount: movies.length, // quantidade de elementos
36        // Os elementos da lista
37        itemBuilder: (context, index) {
38          // Vai ser um item de lista tipo ListTile
39          return ListTile(
40            // Uma imagem de avatar redondinho com a imagem do filme
41            leading: CircleAvatar(
42              backgroundImage: NetworkImage(
43                movies[index].image,
44              ),
45            ),
46            // No título é o nome do filme
47            title: Text(
48              movies[index].name,
49              style: TextStyle(fontSize: 20.0, color: Colors.black),
50            ),
51            // No subtítulo colocamos o link
52            subtitle: Text(movies[index].link),
53            // Ação de clicar
54            onTap: () {
55              // Abrimos uma nova página, outra classe, que está no arquivo
56              // detail.dart. Veja que é um MaterialPageRote, tipo o
57              // MaterialApp, só que é só uma página nova.
58              Navigator.push(
59                context,
60                new MaterialPageRoute(
61                  builder: (context) => DetailPage(movies[index]),
62                ),
63              );
64            },
65          );
66        },
67      ),
68    );
69  }
70}

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  DetailPage(this.movie);
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: new EdgeInsets.all(10.0),
21        child: Column(
22          children: [
23            Center(
24              child: Image(
25                image: NetworkImage(
26                  movie.image,
27                ),
28              ),
29            ),
30            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.