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

De Aulas
Linha 164: Linha 164:
 
<syntaxhighlight lang=dart line>
 
<syntaxhighlight lang=dart line>
 
import 'package:flutter/material.dart';
 
import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart';
+
import 'package:movies/details.dart';
import 'package:flutter_linkify/flutter_linkify.dart';
+
import 'dart:convert';
 
import 'api.dart';
 
import 'api.dart';
  
 
// Uma página para mostrar os detalhes de cada filme. Passamos o objeto
 
// Uma página para mostrar os detalhes de cada filme. Passamos o objeto
 
// do filme como parâmetro no constructor
 
// do filme como parâmetro no constructor
class DetailPage extends StatelessWidget {
+
class MoviesListView extends StatefulWidget {
   final Movie movie;
+
   const MoviesListView({super.key});
  
   const DetailPage(this.movie, {super.key});
+
   @override
 +
  State<StatefulWidget> createState() => _MoviesListViewState();
 +
}
 +
 
 +
class _MoviesListViewState extends State<MoviesListView> {
 +
  List<Movie> movies = List<Movie>.empty();
 +
  String search = "attack on titan";
 +
 
 +
  _MoviesListViewState() {
 +
    API.getMovie(search).then((response) {
 +
      setState(() {
 +
        Iterable list = json.decode(response.body);
 +
        movies = list.map((model) => Movie.fromJson(model)).toList();
 +
      });
 +
    });
 +
  }
  
 
   @override
 
   @override
Linha 179: Linha 194:
 
     return Scaffold(
 
     return Scaffold(
 
       appBar: AppBar(
 
       appBar: AppBar(
         title: Text(movie.name),
+
         title: const Text('Lista de Filmes'),
 
       ),
 
       ),
       body: Container(
+
       body: ListView.builder(
         padding: const EdgeInsets.all(10.0),
+
         itemCount: movies.length,
         child: Column(
+
         itemBuilder: (context, index) {
           children: [
+
           return ListTile(
             Center(
+
             leading: CircleAvatar(
               child: Image(
+
               backgroundImage: NetworkImage(
                 image: NetworkImage(
+
                 movies[index].image,
                  movie.image,
 
                ),
 
 
               ),
 
               ),
 
             ),
 
             ),
             const Text("Link:"),
+
             title: Text(
            // Aqui a gente coloca um link clicável.
+
              movies[index].name,
            Linkify(
+
               style: const TextStyle(
               onOpen: (link) async {
+
                 fontSize: 20.0,
                 if (await canLaunch(movie.link)) {
+
                 color: Colors.black,
                  await launch(movie.link);
+
               ),
                 } else {
 
                  throw 'Não foi possível abrir {$movie.link}';
 
                }
 
              },
 
               text: movie.link,
 
 
             ),
 
             ),
          ],
+
            subtitle: Text(movies[index].url),
         ),
+
            onTap: () {
 +
              Navigator.push(
 +
                context,
 +
                MaterialPageRoute(
 +
                  builder: (context) => DetailPage(movies[index]),
 +
                ),
 +
              );
 +
            },
 +
          );
 +
         },
 
       ),
 
       ),
 
     );
 
     );

Edição das 20h23min de 7 de outubro de 2022

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: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.