0% ont trouvé ce document utile (0 vote)
410 vues95 pages

Cours Flutter

Transféré par

khalilkossentini69
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd
0% ont trouvé ce document utile (0 vote)
410 vues95 pages

Cours Flutter

Transféré par

khalilkossentini69
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd

Flutter

Par Marweni Afef

2024-2025
PLAN
Introduction à Flutter

Les bases de Dart pour Flutter

Introduction aux widgets

Exemples de widgets

Les routes

Récupérer des données à partir d'un service Web

Firebase Cloud Firestore


Introduction
à Flutte r
INTRODUCTION À FLUTTER
Qu'est-ce que Flutter ?

• Flutter est un Framework d'interface utilisateur open source de Google.


• Flutter permettant de créer des applications de haute qualité sur iOS, Android, Web,
Bureau et Embedded à partir d'une seule base de code.
• Flutter permettant de créer des applications multiplateformes compiler en natif.
• La première version de Flutter a été publié le 4 décembre 2018.
• Dans la version 2.0.0 de Flutter plusieurs bugs et problème ont été résolus, de plus la
version Web est désormais qualifiée de stable. Cette version a été publié le 6 mai
2021.

4
INTRODUCTION À FLUTTER
Qu'est-ce que Dart ?

• Dart est un langage de programmation pour les applications multiplateformes.


• Développé par Google.
• Dart est un langage orienté objet, avec une syntaxe de type C.
• Dart se compile en code natif.

5
Technologi es
Applications natives
Android iOS
▸ ▸ Objective-C
TECHNOLOGIES

Java
▸ Kotlin (2017) ▸ Swift (2014)

Avantages Inconvénients

▸ Performances ▸ 1 application par plateforme


▸ Interface spécifique à ▸ Coûts et temps de développement
chaque plateforme

7
Applications hybrides

▸ Cordova, Ionic, …

TECHNOLOGIES

Basées sur des technologies web (HTML, JS, CSS, ...)


▸ Utilisent les WebView (navigateur web intégré)

Avantages Inconvénients
▸ Code partagé / réutilisation ▸ Performances
▸ ( Interface uti l i sateur
▸ Sécurité
spéci fique à chaque
plateforme)

8
Applications cross-plateformes
• Exemples de framework : React Native, Xamarin, Flutter
• Objectif : générer 1 application Android et iOS à partir du même code
TECHNOLOGIES

Avantages Inconvénients
• Code partagé / réutilisation • Peut nécessiter d’écrire du code
• Compétences similaires au web spécifique

9
Quelques
chiffres
QUELQUES CHIFFRES
Google Trends

[Link]

11
QUELQUES CHIFFRES
Stack Overflow Trends

Source :[Link]
12
INTRODUCTION À FLUTTER
Installation de l’environnement

[Link]

13
Les bases de
Dart pour
Flutter
LES BASES DE DART POUR FLUTTER
Conventions de nommage

• snake_case (ex : "home_screen.dart")


– Noms de fichier
• UpperCamelCase (ex : "HomeScreen")
– Classes
– Constructeurs
• lowerCamelCase (ex : "toJson")
– Méthodes
– Variables
– Constantes

15
LES BASES DE DART POUR FLUTTER
Les types en Dart
• Tout ce qui est placé dans une variable est un objet, y compris les types "int", "double",
"bool" et "null"
int a = 5;

• Si vous ne préciser par un type à une variable, Dart va


automatiquement le déduire
var a = 5;

• Le type "dynamic" équivaut à tout type


dynamic a = 5;
a = "toto";

16
LES BASES DE DART POUR FLUTTER
Les lists et les maps
• List : • Map :
Pas de type "Array" dans Dart

Map<String, int> map1 = Map();


List<int> liste1 = List(); Map<String, int> map2 = {'var1': 1, 'var2': 2};
List<int> liste2 = [];
List<int> liste3 = [1, 2, 3]; print(map2['var1']); // Affiche 1
Map<String, dynamic> map3 = Map();
List<dynamic> liste4 = [1, 'Hello', 3.3];
List liste5 = [4, "ma liste"]; map3['toto'] = 'titi';

print(liste3[0]); // Affiche 1 map3['tata'] = 3;

[Link](4); Map map4 = Map(); // <=> Map<dynamic, dynamic>


print([Link]); // Affiche 4
map4['toto'] = 'titi';
map4[4] = 8;
print(map4[4]); // Affiche 8

17
LES BASES DE DART POUR FLUTTER
Les structures de contrôle
if (age < 14)
{ print('Enfants');
} else if (age< 24)
{ print('Adolescents');

} else {
print('Adultes');
}

bool isPublic = true;


String visibility = isPublic ? 'public' : 'private';

18
LES BASES DE DART POUR FLUTTER
Les boucles
List<String> students = ['s1', 's2', 's3'];
for (var student in students) {
print(student);
}

for (var i = 0; i < [Link]; i++) {


print(students[i]);
}

while (year < 2016) {


year += 1;
}

// foreach((String) → void f) → void

[Link]((student) {
print(student);
});

[Link]().forEach((index, student)
{
print('$index: $student');
});
19
LES BASES DE DART POUR FLUTTER
Les fonctions
int somme(int a, int b) {
return a + b;
}

int somme([int a=0, int b=0]) {


return a + b;
}

int s= somme(1, 2);

int somme({required int a, required int b}) {


return a + b;
}

int s= somme(a: 1, b: 2);

20
LES BASES DE DART POUR FLUTTER
Les classes
class Person {
String name;
Person([Link]);
}

Person(String name) {
[Link] = name;
}

Person p = Person("toto");

21
Introduction
aux widget s
INTRODUCTION AUX WIDGETS
Qu'est-ce qu'un widget ?

• Dans Flutter, tout est widget !


• Le rôle principal d’un widget est de faire un
rendu via la méthode "build()"
• Les widgets sont organisés sous forme
d’arborescence
• La méthode "runApp" accepte uniquement
un type Widget en paramètre

23
INTRODUCTION AUX WIDGETS
Les widgets Stateless

• Pas d’état (pas de state)


• Comporte une seule méthode : "Widget
build(BuildContext context)"
• Ne peut pas être "re-builder" par lui-même
• Cycle de vie :
• Initialisation
• Rendu (méthode build())

24
INTRODUCTION AUX WIDGETS
Les widgets Stateless

class MyApp extends StatelessWidget {


@override
Widget build(BuildContext context) {
return Container();
}
}

25
INTRODUCTION AUX WIDGETS
Les widgets Stateful

• Comporte un état
• La méthode "build()" est déportée dans le state
• Une seule méthode : "State<T> createState()" où
<T> correspond à la classe StatefulWidget
• Méthode "build" appelée à chaque chaque
modification du state
• State = ensemble des attributs de la classe State
• "initState()" : méthode pour initialisation le state

26
INTRODUCTION AUX WIDGETS
Les widgets Stateful

• Comporte un état
• La méthode "build()" est déportée dans le state
• Une seule méthode : "State<T> createState()" où
<T> correspond à la classe StatefulWidget
• Méthode "build" appelée à chaque modification du
state
• State = ensemble des attributs de la classe State
• "initState()" : méthode pour initialisation le state

27
INTRODUCTION AUX WIDGETS
Les widgets Stateful
class MyApp extends StatefulWidget {

@override
_MyAppState createState() =>
_MyAppState();
}

class _MyAppState extends State<MyApp> {


late int _counter;

@override
void initState() {
_counter = 0;
[Link]();
}

@override
Widget build(BuildContext context) {
return Text("Compteur $_counter");
}
}

28
INTRODUCTION AUX WIDGETS
Le widget Text

Text(
"Compteur $_counter",
style: TextStyle(
fontWeight: [Link],
fontSize: 16,
color: [Link],
),
);

29
INTRODUCTION AUX WIDGETS
Le widget Image
[Link]
assets:
- assets/image/

Center(
child: [Link]("assets/image/
my_image.jpg"),
)

[Link]('[Link]

30
INTRODUCTION AUX WIDGETS
Le widget Scaffold
Scaffold(
appBar: AppBar(
title: Text("My app"),
),
body: Center(
child: Text("Home page"),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
print("clicked");
},
child: Icon([Link]),
),
bottomNavigationBar: BottomNavigationBar(
items: [
BottomNavigationBarItem(
label: "home",
icon: Icon([Link])
),
BottomNavigationBarItem(
label: "calendar",
icon: Icon(Icons.calendar_today)
),
BottomNavigationBarItem(
label: "contact",
icon: Icon(Icons.contact_mail)
),
],
),
) 31
Les widgets
de layout
LES WIDGETS DE LAYOUT
Le widget container

Center(
child: Container(
height: 100,
width: 200,
color: [Link],
margin: [Link](20),
child: Center(
child: Text("Home page")
),
),
)

33
LES WIDGETS DE LAYOUT
Le widget padding
Center(
child: Container(
height: 100,
width: 200,
color: [Link],
margin: [Link](20),
child: Padding(
padding: const [Link](8.0),
child: Container(
color: [Link],
child: Center(
child: Text("Home page")
),
),
),
),
)

34
LES WIDGETS DE LAYOUT
Le widget column
SingleChildScrollView(
child: Column(
Container( height:
children: [
100,
Container(
color: [Link][400],
height: 100,
),
color: [Link][900],
Container( height:
),
100,
Container( height:
100, color: [Link][300],
),
color: [Link][800],
Container( height:
),
100,
Container( height:
100, color: [Link][200],
),
color: [Link][700],
Container( height:
),
100,
Container( height:
color: [Link][100],
100,
),
color: [Link][600],
),
],
Container( height:
),
100,
),
color: [Link][500],
),

35
LES WIDGETS DE LAYOUT

Le widget column
36

-
),

Le widget row
Container( width:
100,
height: 100,
color: [Link][800],
),
LES WIDGETS DE LAYOUT

Container( width:
100,
height: 100,
color: [Link][700],
),
Container( width:
100,
height: 100,
color: [Link][600],
),
Container( width:
100,
height: 100,
color: [Link][500],
),
Container( width:
100,
height: 100,
color: [Link][400],
),
Container( width:
100,
height: 100,
color: [Link][300],
),
Container( 37
width: 100,
LES WIDGETS DE LAYOUT

Le widget row
LES WIDGETS DE LAYOUT
Le widget ListTile

ListTile(
leading: FlutterLogo(size: 56.0),
title: Text('Two-line ListTile'),
subtitle: Text('Here is a second
line'),
trailing: Icon(Icons.more_vert),
)

39
Les widgets
relatif s aux
l istes
Le widget ListView
LES WIDGETS RELATIFS AUX LISTES

ListView(
children: [
Container(
width: 100,
height: 100,
color: [Link][900],
),
Container(
width: 100,
height: 100,
color: [Link][800],
),
Container(
width: 100,
height: 100,
color: [Link][700],
),
Container(
width: 100,
height: 100,
color: [Link][600],
),
],
)

41
Le widget ListTile
LES WIDGETS RELATIFS AUX LISTES

ListView(
children: [
ListTile(
leading: Icon(Icons.supervised_user_circle),
title: Text("my name"),
subtitle: Text("my job"),
trailing: Icon([Link]),
),
ListTile(
leading: Icon(Icons.supervised_user_circle),
title: Text("my name"),
subtitle: Text("my job"),
trailing: Icon([Link]),
),
ListTile(
leading: Icon(Icons.supervised_user_circle),
title: Text("my name"),
subtitle: Text("my job"),
trailing: Icon([Link]),
),
],
)

42
Les widgets
d’ Informations
LES WIDGETS D’INFORMATIONS
Card
Card(
child: Column(
mainAxisSize: [Link],
children: <Widget>[
const ListTile(
leading: Icon([Link]),
title: Text('The Enchanted Nightingale'),
subtitle: Text('Music by Julie Gable. Lyrics by
Sidney Stein.'),
),
Row(
mainAxisAlignment: [Link],
children: <Widget>[
TextButton(
child: const Text('BUY TICKETS'),
onPressed: () {/* ... */},
),
const SizedBox(width: 8),
TextButton(
child: const Text('LISTEN'),
onPressed: () {/* ... */},
),
const SizedBox(width: 8),
],
),
],
),
) 44
LES WIDGETS D’INFORMATIONS
ProgressIndicator

Column(
mainAxisAlignment:
[Link],
children: [
CircularProgressIndicator(),
SizedBox(height: 50,),
LinearProgressIndicator()
],
)

45
LES WIDGETS D’INFORMATIONS
Tooltip
Tooltip(
message: 'I am a Tooltip',
decoration: BoxDecoration(
borderRadius: [Link](25),
gradient:
LinearGradient(
colors: <Color>[
[Link].shade900,
[Link][400]!
]
),
),
height: 50,
padding: const [Link](8.0),
preferBelow: true,
textStyle: const TextStyle(
fontSize: 24,
color: [Link]
),
showDuration: Duration(seconds: 3),
child: Text('Hover over the text to show a
tooltip.'),
)

46
LES WIDGETS D’INFORMATIONS
AlertDialog
Future<void> _showMyDialog() async {
return showDialog<void>(
context: context,
barrierDismissible: false, // user must tap button!
builder: (BuildContext context) {
return AlertDialog(
title: const Text('AlertDialog Title'),
content: SingleChildScrollView(
child: ListBody(
children: const <Widget>[
Text('This is a demo alert dialog.'),
Text('Would you like to approve of this
message?'),
],
),
),
actions: <Widget>[
TextButton(
child: const Text('Approve'),
onPressed: () {
[Link](context).pop();
},
),
],
);
},
);
} 47
Les widgets
d’ Input et de
sélectio n
TextField
LES WIDGETS D’INPUT ET DE SÉLECTION

TextField(
decoration: InputDecoration(
border: OutlineInputBorder(
borderRadius:
[Link]([Link](10.0)),
),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: [Link]),
borderRadius:
[Link]([Link](10.0)),
),
hintText: "your text",
label: Text("label"),
fillColor: Colors.white70
),
)

border:
UnderlineInputBorder(),

49
2023 - 2024
TextField
LES WIDGETS D’INPUT ET DE SÉLECTION

TextField(
obscureText: true,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Password',
),
),

TextEditingController controller = TextEditingController();

TextField(
controller: controller,
obscureText: true,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Password',
),
),
50
Form
LES WIDGETS D’INPUT ET DE SÉLECTION

final _formKey =
GlobalKey<FormState>();

Form(
key: _formKey,
child: Column(
children: [],
)
)
TextFormField(
ElevatedButton(
decoration: const InputDecoration(
onPressed: () {
border: OutlineInputBorder(),
if (_formKey.currentState!.validate()) {
labelText: 'Email',
[Link](context).showSnackBar(
hintText: 'Enter Email' const SnackBar(content: Text('Processing
),
Data')),
autovalidateMode:
);
}
[Link],
},
validator: (value) {
child: const Text('Submit'),
if (value!.isEmpty) { )
return "* Required";
} else if (![Link]())
{
return "Check your email";
} else
return null;
}, 51
)
Form
LES WIDGETS D’INPUT ET DE SÉLECTION

Form( if (value!.isEmpty) {
key: _formKey, return "* Required";
child: Column( } else if ([Link] < 6) {
children: <Widget>[ return "Password should be atleast 6
TextFormField( characters";
decoration: const InputDecoration( } else if ([Link] > 15) {
border: OutlineInputBorder(), return "Password should not be
labelText: 'Email', greater than 15 characters";
hintText: 'Enter Email' } else
), return null;
validator: (value) { },
if (value!.isEmpty) { ),
return "* Required"; const SizedBox(height: 16,),
} else if (![Link]()) { ElevatedButton(
return "Check your email"; onPressed: () {
} else if (_formKey.currentState!.validate())
return null; {
},
), [Link](context).showSnackBar(
const SizedBox(height: 16,), const SnackBar(content:
TextFormField( Text('Processing Data')),
decoration: const InputDecoration( );
border: OutlineInputBorder(), }
labelText: 'Password', },
hintText: 'Enter secure password' child: const Text('Submit'),
), )
obscureText: true, ],
validator: (value) { ), 52
LES WIDGETS D’INPUT ET DE SÉLECTION

Form
Checkbox
LES WIDGETS D’INPUT ET DE SÉLECTION

Row(
children: [
Checkbox(
checkColor: [Link],
value: isChecked,
onChanged: (bool? value) {
setState(() {
isChecked = value!;
});
},
),
const Text("label")
],
),

54
Radio
LES WIDGETS D’INPUT ET DE SÉLECTION

Text("groupe 1"), Text("groupe 2"),


ListTile( ListTile(
title: const Text('A'), title: const Text('C'),
leading: Radio<String>( leading: Radio<String>(
value: "a", value: "c",
groupValue: _character, groupValue: _character2,
onChanged: (String? value) { onChanged: (String? value) {
ListTile(
setState(() { setState(() {
title: const Text('E'),
_character = value!; _character2 = value!;
leading: Radio<String>(
}); });
value: "e",
}, },
groupValue: _character2,
), ),
onChanged: (String? value) {
), ),
setState(() {
ListTile( ListTile(
_character2 = value! ;
title: const Text('B'), title: const Text('D'),
});
leading: Radio<String>( leading: Radio<String>(
},
value: "b", value: "d",
),
groupValue: _character, groupValue: _character2,
),
onChanged: (String? value) { onChanged: (String? value) {
setState(() { setState(() {
_character = value!; _character2 = value!;
}); });
}, },
), ),
), ),

55
Les widgets
de Bouton
LES WIDGETS DE BOUTON
ElevatedButton et OutlinedButton
ElevatedButton(
onPressed: () {},
style: [Link](
shape: RoundedRectangleBorder(
borderRadius: [Link](30.0),
),
),
child: const Text(' Elevated Button', style: TextStyle(fontSize:
18),)
),
const SizedBox(height: 12,),
ElevatedButton(
onPressed: () {},
child: const Text(' Elevated Button', style: TextStyle(fontSize:
18),)
),

OutlinedButton(
onPressed: () {
debugPrint('Received click');
},
child: const Text('Click Me'),
)

57
LES WIDGETS DE BOUTON
FloatingActionButton et IconButton
const SizedBox(height: 12,),
FloatingActionButton(
onPressed: () {},
child: const
Icon([Link]),
),
const SizedBox(height: 12,),
[Link](
onPressed: () {},
label: const Text("image"),
icon: const Icon([Link]),
),

IconButton(
onPressed: () {},
icon: const Icon([Link])
),

58
LES WIDGETS DE BOUTON
TextButton et InkWell
TextButton(
style: [Link](
textStyle: const TextStyle(fontSize:
20),
),
onPressed: () {},
child: const Text('Text'),
)

InkWell(
onTap: () {},
child: const
Text('Text')
)

InkWell(
onTap: () {},
child: Container(
color: [Link],
child: const Text(
'Text',
style: TextStyle(color: [Link]),
)
)
) 59
Les routes
Navigation vers une nouvelle page
ElevatedButton(
onPressed: () {
[Link](
LES ROUTES

context,
MaterialPageRoute(
builder: (context) => SecondRoute()),
);
},
child: const Text("click")
)

61
Navigation avec des routes nommées
MaterialApp(
title: 'Named Routes Demo',
initialRoute: '/',
routes: {
LES ROUTES

'/': (context) => const FirstScreen(), widget.


'/second': (context) => const SecondScreen(),
},
)
)

ElevatedButton(
onPressed: () {
[Link](context,
'/second');
},
child: const Text("click")
)

62
LES ROUTES
Revenir à la page précédente

ElevatedButton(
onPressed: () {
[Link](context);
},
child: const Text("Back")
)

63
Passage de données entre les Widgets

-
Routes nommées
Envoyer
[Link](context).pushNamed("/second", arguments: "argument
1");
LES ROUTES

Récupérer
final args =
[Link](context)!.[Link];

Routes non nommées


Envoyer Récupérer Accéder StatefulWidget
class MyWidget extends StatefulWidget {
MyWidget( String param1; Text(
param1: "text 1", String param2; widget.param1
param2: "Text 2", MyWidget({ )
)
required this.param1,
required this.param2 Accéder StatelessWidget
});
@override Text(
_MyWidgetState createState() => param1
_MyWidgetState(); )
64
}
Récupére r des
données à
partir d' un
servic e Web
Architecture
RÉCUPÉRER DES DONNÉES À PARTIR D'UN SERVICE WEB

Net

[Link]
Model Service

[Link]

Interface

66
Architecture
RÉCUPÉRER DES DONNÉES À PARTIR D'UN SERVICE WEB

service global_widge
models pages
s ts

[Link] [Link] login [Link]


[Link]
[Link] [Link]
rtuser_se [Link]
rt app_sc
rt rt da
rvice. rt .d
affold
rt rt local_widget art
s logi
logi
n.d login
logi n.d
logi
n.d art _he
logi art
ader
artn.d .dart
artn.d
art

home 67
Model class Article {
RÉCUPÉRER DES DONNÉES À PARTIR D'UN SERVICE WEB

Article({
[Link],
[Link],
[Link],
[Link],
[Link],
[Link],
[Link],
[Link],
});

final Source? source;


final String? author;
final String? title;
final String? description;
final String? url;
final String? urlToImage;
final DateTime? publishedAt;
final String? content;
}
68
Model
RÉCUPÉRER DES DONNÉES À PARTIR D'UN SERVICE WEB

factory [Link](Map<String, dynamic> json) => Article(


source: json["source"] == null ? null :
[Link](json["source"]),
author: json["author"] == null ? null : json["author"],
title: json["title"] == null ? null : json["title"],
description: json["description"] == null ? null :
json["description"],
url: json["url"] == null ? null : json["url"],
urlToImage: json["urlToImage"] == null ? null : json["urlToImage"],
publishedAt: json["publishedAt"] == null ? null :
[Link](json["publishedAt"]),
content: json["content"] == null ? null : json["content"],
);
[Link](Map<String, dynamic> json) {
OU
source= json["source"] == null ? null : [Link](json["source"]);
author= json["author"] == null ? null : json["author"];
title= json["title"] == null ? null : json["title"];
description= json["description"] == null ? null : json["description"];
url= json["url"] == null ? null : json["url"];
urlToImage= json["urlToImage"] == null ? null : json["urlToImage"];
publishedAt= json["publishedAt"] == null ? null :
[Link](json["publishedAt"]);
content= json["content"] == null ? null : json["content"];
} 69
Model
RÉCUPÉRER DES DONNÉES À PARTIR D'UN SERVICE WEB

Map<String, dynamic> toJson() => {


"source": source == null ? null : source!.toJson(),
"author": author == null ? null : author,
"title": title == null ? null : title,
"description": description == null ? null : description,
"url": url == null ? null : url,
"urlToImage": urlToImage == null ? null : urlToImage,
"publishedAt": publishedAt == null ? null : publishedAt!.toIso8601String(),
"content": content == null ? null : content,
};
Map<String, dynamic> toJson() { OU
Map<String, dynamic> data = Map<String, dynamic>();
data["source"] = source == null ? null : source!.toJson();
data["author"] = author == null ? null : author;
data["title"] = title == null ? null : title;
data["description"] = description == null ? null : description;
data["url"] = url == null ? null : url;
data["urlToImage"] = urlToImage == null ? null : urlToImage;
data["publishedAt"] = publishedAt == null ? null :
publishedAt!.toIso8601String();
data["content"] = content == null ? null : content;
return data;
70
}
Model
RÉCUPÉRER DES DONNÉES À PARTIR D'UN SERVICE WEB

Data dataFromJson(String str) => [Link]([Link](str));

String dataToJson(Data data) => [Link]([Link]());

71
service
RÉCUPÉRER DES DONNÉES À PARTIR D'UN SERVICE WEB

installer la dépendance

[Link]
http

[Link]
dependencies:
run
http: ^0.13.4 flutter pub get

import 'package:http/[Link]' as
http;

72
service
RÉCUPÉRER DES DONNÉES À PARTIR D'UN SERVICE WEB

class NewsService{
Future<Data> getAll() async {
var url = [Link]('[Link]
country=us&category=business&apiKey=e0ac43cc665a48aeb762ed7dae8139e9'
);
var response = await [Link](url,);
print('Response status: ${[Link]}');
print('Response body: ${[Link]}');
return dataFromJson([Link]);
}
}
Map<String, String> queryParameters = {
"country": "us",
"category": "business",
"apiKey":
"e0ac43cc665a48aeb762ed7dae8139e9",
};
var url = Uri(
scheme: 'https',
host: '[Link]',
path: '/v2/top-headlines',
queryParameters: queryParameters,
73
);
Interface
RÉCUPÉRER DES DONNÉES À PARTIR D'UN SERVICE WEB

-
NewsService newsService= NewsService();

[Link]().then((value) {
print([Link]!.[Link]);
});

OU
Data data = await
[Link]();

OU
74
Interface
RÉCUPÉRER DES DONNÉES À PARTIR D'UN SERVICE WEB

NewsService newsService= NewsService();

FutureBuilder(
future: [Link](),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if ([Link]) {
return OnSucces(
data: [Link],
);
} else if ([Link]) {
return OnError(
error: [Link](),
);
} else {
return const Waiting();
}
},
) 75
Interface
RÉCUPÉRER DES DONNÉES À PARTIR D'UN SERVICE WEB

class OnError extends StatelessWidget {


final String error;
OnError({
Key? key,
required [Link]
}) : super(key: key);

@override
Widget build(BuildContext context) {
return Center(
child: Column(
mainAxisAlignment: [Link],
children:<Widget>[
const Icon(
Icons.error_outline,
color: [Link],
size: 60,
),
Padding(
padding: const [Link](top: 16),
child: Text('Error: ${error}'),
)
]
)
);
}
}
76
Interface
RÉCUPÉRER DES DONNÉES À PARTIR D'UN SERVICE WEB

class Waiting extends StatelessWidget {


const Waiting({
Key? key,
}) : super(key: key);

@override
Widget build(BuildContext context) {
return Center(
child: Column(
mainAxisAlignment: [Link],
children:const <Widget>[
SizedBox(
width: 60,
height: 60,
child: CircularProgressIndicator(),
),
Padding(
padding: [Link](top: 16),
child: Text('Awaiting result...'),
)
]
)
);
}
}

77
Interface
RÉCUPÉRER DES DONNÉES À PARTIR D'UN SERVICE WEB

class OnSucces extends StatelessWidget {


final Data data;
OnSucces({
Key? key,
required [Link]
}) : super(key: key);

@override
Widget build(BuildContext context) {
return Center(
child: Column(
mainAxisAlignment: [Link],
children: <Widget>[
const Icon(
Icons.check_circle_outline,
color: [Link],
size: 60,
),
Padding(
padding: const [Link](top: 16),
child: Text('Result: $
{[Link]!.[Link]}'),
)
]
),
);
}
} 78
Firebase Cloud
Firestore
Créer un projet Firebase

• Accédez à la console Firebase et cliquez sur


Ajouter un projet.

• Saisissez un nom de projet et cliquez sur


Continuer .

80
Intégration de Firebase avec Android, iOS et Web

Sélectionnez l'icône de la plate-forme souhaitée dans le tableau de bord Firebase.

81
Configuration de la plate-forme Web

• Sélectionnez l'icône Web sur le tableau de bord.

82
Configuration de la plate-forme Web

• Entrez le pseudo de l'application et cliquez sur Enregistrer l'application

83
Configuration de la plate-forme Web

• Ajouter le SDK Firebase

84
Activer Cloud Firestore
• Vous pouvez activer la base de données Firestore en sélectionnant Firestore dans le
menu de gauche, puis en cliquant sur Créer une base de données.

85
Ajout de Firebase à Flutter

• firebase_core : requis pour l'initialisation de Firebase et l'utilisation de tout autre plugin


Firebase.
• cloud_firestore : requis pour interagir avec la base de données Firestore.

86
Initialisation
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/[Link]';

Future<void> main() async {


[Link]();
await [Link](
options: const FirebaseOptions(
apiKey: "AIzaSyB_Qlovx15Cx_-h5TPzaBog8oRW4e8ykd8",
authDomain: "[Link]",
projectId: "blog-930aa",
storageBucket: "[Link]",
messagingSenderId: "252280810021",
appId: "1:252280810021:web:e6668c21a58d92edd86dcc",
measurementId: "G-R7TG59DGRQ"
)
);
runApp(const MyApp());
}
87
Model
class Article {
Article({
[Link],
required [Link],
required [Link],
[Link],
});

final String? id;


final DateTime? createdAt;
final String title;
final String body;

factory [Link](QueryDocumentSnapshot query) => Article(


id: [Link],
title: query["title"],
body: query["body"],
createdAt: ([Link]() as Map).containsKey("createdAt") ? query["createdAt"].toDate() :
null,
);

Map<String, dynamic> toJson() => {


"title": title,
"body": body,
"createdAt": [Link](),
};
} 88
Ajouter un document
import 'package:cloud_firestore/cloud_firestore.dart';

final FirebaseFirestore firestore = [Link];

Article article =Article(


title: "codicem nondum per aetatem firmato",
body: "Circa Phalangio Baeticae consulari cecidit funesti
carnificis."
);
[Link]('articles').add(
[Link]()
);

89
Afficher liste des documents
import 'package:cloud_firestore/cloud_firestore.dart';

final FirebaseFirestore firestore = [Link];

FutureBuilder(
future: [Link]("articles")
.orderBy("createdAt",descending: true)
.get(),
builder: (context, snapshot) {
if([Link]){
return OnError(message: [Link]());
} else if([Link]){
QuerySnapshot collection = [Link] as QuerySnapshot;
return BuildListArticle(collection: collection);
} else {
return const Center(
child: CircularProgressIndicator()
);
}
},
)
90
Afficher liste des documents
import 'package:cloud_firestore/cloud_firestore.dart';

final FirebaseFirestore firestore = [Link];

StreamBuilder(
stream: [Link]("articles")
.orderBy("createdAt",descending: true)
.snapshots(includeMetadataChanges: true),
builder: (context, snapshot) {
if([Link]){
return OnError(message: [Link]());
} else if([Link]){
QuerySnapshot collection = [Link] as
QuerySnapshot;
return BuildListArticle(collection: collection);
} else {
return const Center(
child: CircularProgressIndicator()
);
}
},
)
91
Afficher liste des documents
class BuildListArticle extends StatelessWidget {
const BuildListArticle({
Key? key,
required [Link],
}) : super(key: key);

final QuerySnapshot<Object?> collection;

@override
Widget build(BuildContext context) {
return [Link](
itemCount: [Link],
itemBuilder: (context, index) {
Article article = [Link]([Link][index]);
return ItemCard(article: article);
},
);
}
}

92
fficher liste des documents
class ItemCard extends StatelessWidget {
const ItemCard({
Key? key,
required [Link],
}) : super(key: key);
final Article article;
@override
Widget build(BuildContext context) {
return Padding(
padding: const [Link](8.0),
child: Card(
elevation: 8,
child: Column(
children: [
Align(
alignment: [Link],
child: Text([Link]!.toIso8601String()),
),
ListTile(
title: Text([Link]),
subtitle: Text([Link]),
),
],
)
),
);
}
} 93
Afficher liste des documents
class OnError extends StatelessWidget {
final String message;
const OnError({
Key? key,
required String [Link],
}) : super(key: key);

@override
Widget build(BuildContext context) {
return Center(
child: Text(message,
style: const TextStyle(color: [Link]),
),
);
}
}

94
MERCI
POUR VOTRE
AT T E N T I O N

Vous aimerez peut-être aussi