Flutter - Consumindo API

De Aulas
Revisão de 13h25min de 10 de março de 2023 por Admin (discussão | contribs) (→‎api.dart)

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

import 'package:flutter/material.dart';
import 'movies.dart';

void main() => runApp(const App());

class App extends StatelessWidget {
  const App({super.key});

  @override
  build(context) {
    return const MaterialApp(
      title: 'Filmes',
      home: MoviesListView(),
    );
  }
}

api.dart

O arquivo api.dart faz referência à API TVMaze e gerencia o objeto de transferência de um filme.

import 'package:http/http.dart' as http;

// A URL da API
const baseUrl = "https://api.tvmaze.com/search/shows?q=";

// Criamos a classe da nossa API. O nome você que escolhe. Fazemos aqui
// uma requisição get (como fizemos no react) e passamos a URL, mas usamos
// um Uri.parse pra transformar a string em uma URI.
class API {
  static Future getMovie(search) async {
    var url = baseUrl + search;
    return await http.get(Uri.parse(url));
  }
}

// Criamos uma classe para representar os objetos que vão conter os filmes
// e colocamos só os campos que vamos usar.
class Movie {
  int id;
  String name;
  String link;
  String image;

  Movie(this.id, this.name, this.link, this.image);

  Movie.fromJson(Map json)
      : id = json['show']['id'],
        name = json['show']['name'],
        link = json['show']['url'],
        image = json['show']['image']['medium'];
}

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:movies/details.dart';
 3import 'dart:convert';
 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 MoviesListView extends StatefulWidget {
 9  const MoviesListView({super.key});
10
11  @override
12  State<StatefulWidget> createState() => _MoviesListViewState();
13}
14
15class _MoviesListViewState extends State<MoviesListView> {
16  List<Movie> movies = List<Movie>.empty();
17  String search = "attack on titan";
18
19  _MoviesListViewState() {
20    API.getMovie(search).then((response) {
21      setState(() {
22        Iterable list = json.decode(response.body);
23        movies = list.map((model) => Movie.fromJson(model)).toList();
24      });
25    });
26  }
27
28  @override
29  Widget build(BuildContext context) {
30    return Scaffold(
31      appBar: AppBar(
32        title: const Text('Lista de Filmes'),
33      ),
34      body: ListView.builder(
35        itemCount: movies.length,
36        itemBuilder: (context, index) {
37          return ListTile(
38            leading: CircleAvatar(
39              backgroundImage: NetworkImage(
40                movies[index].image,
41              ),
42            ),
43            title: Text(
44              movies[index].name,
45              style: const TextStyle(
46                fontSize: 20.0,
47                color: Colors.black,
48              ),
49            ),
50            subtitle: Text(movies[index].url),
51            onTap: () {
52              Navigator.push(
53                context,
54                MaterialPageRoute(
55                  builder: (context) => DetailPage(movies[index]),
56                ),
57              );
58            },
59          );
60        },
61      ),
62    );
63  }
64}

Atividades

Desafio 1

  1. Implemente o exemplo anterior em seu computador.
  2. Adicione um campo texto e um botão "Procurar". Quando clicar no botão procurar, atualiza a lista de filmes conforme a string do campo texto.

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.