Escolar Documentos
Profissional Documentos
Cultura Documentos
main
1 contributor
Controlo de Versões
Table 1. Histórico de Versões
Data Autor Versão Descrição Validado
Especificações Técnicas
Este manual destina-se a qualquer pessoa que deseje organizar e acolher informações
sobre Providers e Consumers ou da comunicação entre backend e frontend na Flutter
Framework, mas também tem a finalidade de servir de guião para iniciantes e aprendizes.
https://github.com/PowerSolution-Academy/documentation/blob/main/frontend/flutter/powersolution-academy-flutter-provider-basics.adoc 1/17
3/16/23, 10:20 PM documentation/powersolution-academy-flutter-provider-basics.adoc at main · PowerSolution-Academy/documentation
Introdução
A Flutter desenvolveu bibliotecas que promovem soluções digitais. Um deles o mais
poderoso é chamado Provider. Neste guia apresenta-se seus benefícios e a sua utilidade
no desenvolvimento de aplicações UI/UX.
O que é Provider?
Na documentação oficial do Flutter encontra-se esta descrição: “é um wrapper do
InheritedWidget para tornar sua implementação mais fácil e reutilizável”.
Imaginemos que quer se partilhar informações através da árvore de widgets e que toda
vez que passamos de uma tela para outra, tivemos que partilhar uma entidade com dados
comuns entre ela. Quão consistente isso pareceria?
https://github.com/PowerSolution-Academy/documentation/blob/main/frontend/flutter/powersolution-academy-flutter-provider-basics.adoc 2/17
3/16/23, 10:20 PM documentation/powersolution-academy-flutter-provider-basics.adoc at main · PowerSolution-Academy/documentation
Como utilizar?
Passo 1 - Adicionar dependência
dependencies:
flutter:
sdk: flutter
provider: <version>
Pode consultar informações da dependência e saber a sua versão mais recente aqui
ChangeNotifier: Este deve ser estendido para fornecer um objeto que pode ser usado para
enviar notificações de alteração para seus ouvintes.
https://github.com/PowerSolution-Academy/documentation/blob/main/frontend/flutter/powersolution-academy-flutter-provider-basics.adoc 3/17
3/16/23, 10:20 PM documentation/powersolution-academy-flutter-provider-basics.adoc at main · PowerSolution-Academy/documentation
No pacote data/models dentro do pacote lib cria-se um novo ficheiro .dart com o
nome da entidade. Vamos utilizar o exemplo de um estudante, então criamos um ficheiro
com nome student.dart .
O modelo deve ter como base o corpo JSON retornado na resposta dada pela API no
backend. Consideremos este exemplo de resposta retornada pela API:
{
"code" : 123456,
"name" : "Joana Patricia Pereira",
"age" : 19,
"course" : "MEDICINE",
"faculty" : "BIO",
"_links" : {
"self" : {
"href" : "http://localhost:8080/students/5a7cc6d9-cc26-4db7-8365-aee937cd0173"
},
"university": {
"href" : "http://localhost:8080/universities/36127889-bf8e-472f-b88f-bda84b27e
}
}
}
Tendo este modelo, vamos definir a classe Student onde seus atributos são os campos
do corpo JSON acima:
class Student {
int? code;
String? name;
int? age;
String? course;
String? faculty;
Links? links;
Student(
{this.code, this.name, this.age, this.course, this.faculty, this.links});
https://github.com/PowerSolution-Academy/documentation/blob/main/frontend/flutter/powersolution-academy-flutter-provider-basics.adoc 4/17
3/16/23, 10:20 PM documentation/powersolution-academy-flutter-provider-basics.adoc at main · PowerSolution-Academy/documentation
Note que o campo _links também contém outros campos como self e university .
Então devemos também criar classes para estes.
class Links {
Self? self;
Self? university;
Links({this.self, this.university});
}
Os campos de self e university têm o mesmo campo href contidos neles, então
podemos definir apenas uma classe para ambas que vamos denominar de Self .
class Self {
String? href;
Self({this.href});
Após definir os campos, iremos criar dois métodos estáticos para cada classe: fromJson e
toJson .
O fromJson serve para serializar os campos retornados pela API em formato JSON para
os campos contidos no modelo que definimos anteriormente. Normalmente utiliza-se para
pedidos do tipo GET quando precisa-se obter dados da API.
O toJson serve para atribuir os campos contidos no modelo definido, para um corpo
JSON para assim enviar no corpo da requisição para a API. É utilizado normalmente para
os pedidos do tipo POST ou PUT quando precisa-se enviar dados para a API.
https://github.com/PowerSolution-Academy/documentation/blob/main/frontend/flutter/powersolution-academy-flutter-provider-basics.adoc 5/17
3/16/23, 10:20 PM documentation/powersolution-academy-flutter-provider-basics.adoc at main · PowerSolution-Academy/documentation
data['code'] = this.code;
data['name'] = this.name;
data['age'] = this.age;
data['course'] = this.course;
data['faculty'] = this.faculty;
if (this.links != null) {
data['_links'] = this.links!.toJson();
}
return data;
}
https://github.com/PowerSolution-Academy/documentation/blob/main/frontend/flutter/powersolution-academy-flutter-provider-basics.adoc 6/17
3/16/23, 10:20 PM documentation/powersolution-academy-flutter-provider-basics.adoc at main · PowerSolution-Academy/documentation
class Student {
int? code;
String? name;
int? age;
String? course;
String? faculty;
Links? links;
Student(
{this.code, this.name, this.age, this.course, this.faculty, this.links});
class Links {
Self? self;
Self? university;
Links({this.self, this.university});
https://github.com/PowerSolution-Academy/documentation/blob/main/frontend/flutter/powersolution-academy-flutter-provider-basics.adoc 7/17
3/16/23, 10:20 PM documentation/powersolution-academy-flutter-provider-basics.adoc at main · PowerSolution-Academy/documentation
class Self {
String? href;
Self({this.href});
A seguir definimos os métodos que irão ser invocados para comunicação com a API. No
pacote services cria-se um novo ficheiro com o nome <nome_do_modelo>_api.dart . No
nosso caso seria student_api.dart .
Ao abrir este ficheiro criaremos uma classe abstrata StudentApi , onde definiremos alguns
métodos baseados nos métodos dos controladores implementados na backend.
Os métodos mais comuns são: obter um estudante pelo id, obter todos os estudantes,
criar um estudante, atualizar um estudante e eliminar um estudante.
Estes métodos operam de forma assíncrona, quando invocados permitem que outras
operações ocorram antes que a sua operação seja completada. Para isto coloca-se a
keyword async no método.
https://github.com/PowerSolution-Academy/documentation/blob/main/frontend/flutter/powersolution-academy-flutter-provider-basics.adoc 8/17
3/16/23, 10:20 PM documentation/powersolution-academy-flutter-provider-basics.adoc at main · PowerSolution-Academy/documentation
Estes métodos demoram algum tempo, e podem não retornar o resultado imediatamente,
então, estes retornarão a promessa de entregar o resultado quando terminar. Isto é
chamado de Future . Por exemplo, a promessa de carregar um número gravada na base
de dados retornaria um Future<int> . Ou uma lista de filmes de uma pesquisa na Internet
poderiar retornar um Future<List<Movie>> . Um Future<T> é algo que no futuro
retornara um T .
Definiremos algumas constantes. A primeira é o endpoint da API ao qual deve ser feito a
requisição. Normalmente cria-se uma classe de configuração no pacote config dentro
do pacote lib denominado AppConfig onde realizai-se as configurações como o DNS e
a porta da API.
https://github.com/PowerSolution-Academy/documentation/blob/main/frontend/flutter/powersolution-academy-flutter-provider-basics.adoc 9/17
3/16/23, 10:20 PM documentation/powersolution-academy-flutter-provider-basics.adoc at main · PowerSolution-Academy/documentation
class AppConfig {
Após definir a classe de configuração em lib\config , cria-se uma variável estática que
denomina-se connectionString (pode ter qualquer outro nome no contexto como:
_apiUrlString, _endpointString, …). Também definimos alguns _headers que irão ser utilizado
nas requisições de obtenção de dados e envio de dados, definidos como getHeaders e
postHeaders respetivamente.
factory RestBuildingApi() {
return _api;
}
RestBuildingApi._instance();
https://github.com/PowerSolution-Academy/documentation/blob/main/frontend/flutter/powersolution-academy-flutter-provider-basics.adoc 10/17
3/16/23, 10:20 PM documentation/powersolution-academy-flutter-provider-basics.adoc at main · PowerSolution-Academy/documentation
Agora implementa-se os métodos necessários para comunicação com a API. Por esta ser
uma classe de implementação faz-se o override dos métodos definidos em StudentApi .
@override
Future<Student> fetchOne(String url) async { }
@override
Future<Student> fetchOne(String url) async {
Student student;
try {
} catch (e) {
throw Exception('Error: Failed to load data from API | Cause: $e');
}
return student;
https://github.com/PowerSolution-Academy/documentation/blob/main/frontend/flutter/powersolution-academy-flutter-provider-basics.adoc 11/17
3/16/23, 10:20 PM documentation/powersolution-academy-flutter-provider-basics.adoc at main · PowerSolution-Academy/documentation
De forma semelhante para o caso de envio de dados, a diferença está na requisição que
passa a ser http.post cabeçalho que passa a ser postHeaders e no uso do método
toJson . O jsonEncode faz a conversão do objeto do tipo Map<String, dynamic> para um
corpo JSON na requisição.
@override
Future<Student> createStudent(Student student, String universityId) async {
Student studentResponse;
Uri uri = Uri.parse(_connectionString);
try {
student.links = {};
return studentResponse;
https://github.com/PowerSolution-Academy/documentation/blob/main/frontend/flutter/powersolution-academy-flutter-provider-basics.adoc 12/17
3/16/23, 10:20 PM documentation/powersolution-academy-flutter-provider-basics.adoc at main · PowerSolution-Academy/documentation
No pacote providers no pacote lib , criar-se um ficheiro que deve ser denominado de
<nome_do_modelo>_provider.dart e cria-se a classe StudentProvider .
notifyListeners();
https://github.com/PowerSolution-Academy/documentation/blob/main/frontend/flutter/powersolution-academy-flutter-provider-basics.adoc 13/17
3/16/23, 10:20 PM documentation/powersolution-academy-flutter-provider-basics.adoc at main · PowerSolution-Academy/documentation
notifyListeners();
}
notifyListeners();
}
notifyListeners();
}
}
A necessidade de vários provedores para desenvolver um app pode ser normal, o que
podemos fazer? Bem, a biblioteca Provider nos deu uma solução chamada
MultiProvider que é uma lista de ChangeNotifierProviders que partilham suas
informações os filhos. Está configurado da seguinte forma no main.dart :
runApp(
MultiProvider(
providers: providers,
child: MaterialApp(
title: 'University Management',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const Home(),
),
),
);
https://github.com/PowerSolution-Academy/documentation/blob/main/frontend/flutter/powersolution-academy-flutter-provider-basics.adoc 14/17
3/16/23, 10:20 PM documentation/powersolution-academy-flutter-provider-basics.adoc at main · PowerSolution-Academy/documentation
initializeApp() async {
List<SingleChildWidget> providers = [
ChangeNotifierProvider(create: (_) => StudentsProvider()),
ChangeNotifierProvider(create: (_) => UniversityProvider()),
];
return providers;
Depois de ter os provedores prontos, basta decidir como usá-los de nossos widgets
através de duas opções:
1. Consumer
@override
Widget build(BuildContext context) {
https://github.com/PowerSolution-Academy/documentation/blob/main/frontend/flutter/powersolution-academy-flutter-provider-basics.adoc 15/17
3/16/23, 10:20 PM documentation/powersolution-academy-flutter-provider-basics.adoc at main · PowerSolution-Academy/documentation
Portanto, usar o Consumer pode ser uma boa ideia quando você deseja acessar as
informações para exibir e atualizar sobre as alterações, não precisa alterar os dados do
Provider .
2. Provider.of
Além disso, pode usá-lo em toda a árvore de widgets. Veja a forma de uso:
@override
Widget build(BuildContext context) {
final studentProvider = Provider.of<StudentProvider>(context);
final universityProvider = Provider.of<UniversityProvider>(context);
return Scaffold(
appBar: AppBar(title: const Text('Página do Estudante'),),
body: Column(
children: [
Text('${studentProvider.name} ', style: GoogleFonts.actor(fontSize: 24),),
ElevatedButton(onPressed: (){
studentProvider.name = 'João Lopes';
universityProvider.name = 'Universidade de Cabo Verde';
}, child: Text('Atualizar nomes', style: GoogleFonts.adventPro(fontSize: 2
],
),
);
}
}
https://github.com/PowerSolution-Academy/documentation/blob/main/frontend/flutter/powersolution-academy-flutter-provider-basics.adoc 16/17
3/16/23, 10:20 PM documentation/powersolution-academy-flutter-provider-basics.adoc at main · PowerSolution-Academy/documentation
Referências
[1] Flutter Provider: What is it, what is it for, and how to use it? - Medium
(bancolombia-tech)
Give feedback
https://github.com/PowerSolution-Academy/documentation/blob/main/frontend/flutter/powersolution-academy-flutter-provider-basics.adoc 17/17