0% ont trouvé ce document utile (0 vote)
116 vues55 pages

Guide Flutter: Développement d'Applications Mobiles Multiplateformes

Transféré par

achraf.talibi
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)
116 vues55 pages

Guide Flutter: Développement d'Applications Mobiles Multiplateformes

Transféré par

achraf.talibi
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

Applications mobiles Cross

Platforms

ELAACHAK LOTFI
2023/2024
Sommaire
Introduction

Architecture de Flutter

Flutter vs React native

Premier Application

Le langage Dart

Les Bases de Flutter

Routage avec Fultter

Flutter et Sqlite

Rest API et Flutter


1. Introduction

1.1 c’est quoi Flutter ?

En général, la création d'une application mobile est une tâche très complexe et difficile. Il existe de
nombreux frameworks disponibles, qui fournissent d'excellentes fonctionnalités pour développer
des applications mobiles. Pour le développement d'applications mobiles, Android fournit un cadre
natif basé sur le langage Java et Kotlin, tandis qu'iOS fournit un cadre basé sur le langage
Objective-C / Swift. Ainsi, nous avons besoin de deux langages et frameworks différents pour
développer des applications pour les deux OS. Aujourd'hui, pour surmonter cette complexité,
plusieurs frameworks ont été introduits qui prennent en charge à la fois les systèmes d'exploitation
et les applications de bureau. Ces types de framework sont connus sous le nom d'outils de
développement multiplateformes « cross plateformes ».

Le cadre de développement multiplateforme a la capacité d'écrire un code et peut se déployer sur les
différentes plates-formes (Android, iOS et Desktop). Cela permet aux développeurs de gagner
beaucoup de temps et d'économiser des efforts de développement.

Flutter est une boîte à outils d'interface utilisateur pour créer des applications rapides, belles et
compilées en natif pour mobile, Web et bureau avec un langage de programmation et une base de
code unique. Il est gratuit et open-source. Il a été initialement développé à partir de Google et est
désormais géré selon une norme ECMA. Les applications Flutter utilisent le langage de
programmation Dart pour créer une application. La programmation de fléchettes partage plusieurs
mêmes fonctionnalités que d'autres langages de programmation, tels que Kotlin et Swift, et peut être
trans-compilée en code JavaScript.

1.2. Qu'est-ce qui rend Flutter unique?

Flutter est différent des autres frameworks car il n'utilise ni WebView ni les widgets OEM fournis
avec l'appareil. Au lieu de cela, il utilise son propre moteur de rendu haute performance pour
dessiner des widgets. Il implémente également la plupart de ses systèmes tels que l'animation, les
gestes et les widgets dans le langage de programmation Dart qui permet aux développeurs de lire,
modifier, remplacer ou supprimer facilement des éléments. Il donne un excellent contrôle aux
développeurs sur le système.

Les propriétés de Flutter :


1.3. Les Avantages

• Il rend le processus de développement d'application extrêmement rapide en raison de la


fonction de rechargement à chaud « Hot Reload ».

• Il offre des expériences de défilement plus fluides et transparentes d'utilisation de


l'application sans trop de blocages ni de coupures, ce qui accélère l'exécution des
applications par rapport à d'autres infrastructures de développement d'applications mobiles.

• Flutter réduit le temps et les efforts de test. Comme nous le savons, les applications Flutter
sont multiplateformes, de sorte que les testeurs n'ont pas toujours besoin d'exécuter le même
ensemble de tests sur différentes plates-formes pour la même application.

• Il possède une excellente interface utilisateur car il utilise un widget centré sur la
conception, des outils de développement élevé, des API avancées et bien d'autres
fonctionnalités.

• Il est similaire à un cadre réactif dans lequel les développeurs n'ont pas besoin de mettre à
jour le contenu de l'interface utilisateur manuellement.

• Il convient aux applications MVP (Minimum Viable Product) en raison de son processus de
développement rapide et de sa nature multiplateforme.

1.3. Les Inconvénients

• Il fournit un accès très limité aux bibliothèques SDK. Cela signifie qu'un développeur n'a
pas beaucoup de fonctionnalités pour créer une application mobile.

• Les applications Flutter ne prennent pas en charge le navigateur. Il ne prend en charge que
les plates-formes Android et iOS.

• Il utilise la programmation Dart pour le codage, donc un développeur doit apprendre de


nouvelles technologies. Cependant, il est facile à apprendre pour les développeurs.

2. Architecture de Flutter

L'architecture Flutter comprend principalement quatre composants.

1. Moteur Flutter
2. Bibliothèque de la Fondation
3. Widgets
4. Concevoir des widgets spécifiques

Moteur Flutter :
Il s'agit d'un runtime portable pour les applications mobiles de haute qualité et principalement basé
sur le langage C ++. Il implémente les bibliothèques principales de Flutter qui incluent l'animation
et les graphiques, les E / S de fichiers et de réseau, l'architecture de plug-in, la prise en charge de
l'accessibilité et un environnement d'exécution de fléchettes pour le développement, la compilation
et l'exécution d'applications Flutter. Il faut la bibliothèque graphique open source de Google, Skia,
pour restituer des graphiques de bas niveau.

Bibliothèque de la Fondation :
Il contient tous les packages requis pour les éléments de base de l'écriture d'une application Flutter.
Ces bibliothèques sont écrites en langage Dart.

Widgets :
Dans Flutter, tout est un widget, qui est le concept central de ce framework. Widget dans le Flutter
est essentiellement un composant d'interface utilisateur qui affecte et contrôle la vue et l'interface de
l'application. Il représente une description immuable d'une partie de l'interface utilisateur et
comprend des graphiques, du texte, des formes et des animations créés à l'aide de widgets. Les
widgets sont similaires aux composants React.

Dans Flutter, l'application est elle-même un widget qui contient de nombreux sous-widgets.

Dans l'exemple ci-dessus, nous pouvons voir que tous les composants sont des widgets qui
contiennent des widgets enfants. Ainsi, l'application Flutter est elle-même un widget.

Couches

Le framework Flutter est catégorisé en fonction de sa complexité et établit une hiérarchie basée sur
le niveau décroissant de ces complexités. Ces catégories sont souvent appelées "couches". Ces
couches sont construites les unes sur les autres. La couche supérieure est un widget spécifique au
système d'exploitation de l'appareil (c'est-à-dire Android ou iOS). La deuxième couche est
constituée des widgets natifs de Flutter, qui comprennent les composants structurels de l'interface
utilisateur, les détecteurs de gestes, les composants de gestion d'état, etc. C'est dans cette troisième
couche que s'effectue le rendu de l'interface utilisateur et de l'état. C'est la couche qui comprend
tous les composants visibles de l'application Flutter. La couche suivante est constituée des
animations utilisées dans les transitions, le flux d'images et les gestes. Ces couches se poursuivent à
un niveau très élevé de la conception du système qui n'est pas l'objet de cet article. Le diagramme
ci-dessous en donne un aperçu :

Concevoir des widgets spécifiques


Le framework Flutter comporte deux ensembles de widgets conformes à des langages de conception
spécifiques. Ce sont Material Design pour l'application Android et Cupertino Style pour
l'application IOS.
3. Flutter vs React native
Concept Flutter React Native

Develop By It is first introduced by Google. It is first introduced by Facebook.

Release May 2017 June 2015

Programmin It uses Dart language to create a mobile It uses JavaScript to create mobile
g Language app. apps.

React Native uses Flux and Redux


architecture. Flux created by
Flutter uses Business Logic Component
Architecture Facebook, whereas Redux is the
(BLoC) architecture.
preferred choice among the
community.

User It uses custom widgets to build the UI of It uses native UI controllers to create
Interface the app. UI of the app.

Flutter documentation is good, organize,


Documentat and more informative. We can get React native documentation is user-
ion everything that we want to be written in friendly but disorganized.
one place.

The performance of the Flutter


The performance of the React Native
application is fast. Flutter compiles the
app is slow in comparison to the
application by using the arm C/C++
Performance Flutter app. Here, sometimes
library that makes it closer to machine
developers face issues while running
code and gives the app a better native
the hybrid application architecture.
performance.

Flutter provides a very rich set of testing


features. This feature allows the React Native uses third-party tools
Testing
developer to perform unit testing, that are available for testing the app.
integration testing, and widget testing.

It has very strong community


Community It has less community support as
support where the questions and
Support compared to React Native.
issues can be solved quickly.

Hot Reload Supported Supported

83200 stars on GitHub (December


Popularity 81200 stars on GitHub (December 2019)
2019)

Industry Google Facebook


Adoption Hamilton Instagram
Reflectly LinkedIn
Xianyu Skype

4. Premier Application
Nous allons apprendre à créer une application simple dans Android Studio/Intellij pour comprendre
les bases de l'application Flutter.

Vérifions la structure de l'application du projet Flutter et son objectif. Dans l'image ci-dessous, vous
pouvez voir les différents dossiers et composants de la structure de l'application Flutter, qui vont
être abordés ici.

idea: ce dossier est tout en haut de la structure du projet, qui contient la configuration pour Android
Studio. Cela n'a pas d'importance car nous n'allons pas travailler avec Android Studio afin que le
contenu de ce dossier puisse être ignoré.

.android: ce dossier contient un projet Android complet et est utilisé lorsque vous créez l'application
Flutter pour Android. Lorsque le code Flutter est compilé dans le code natif, il est injecté dans ce
projet Android, de sorte que le résultat est une application Android native. Par exemple: lorsque
vous utilisez l'émulateur Android, ce projet Android est utilisé pour créer l'application Android, qui
s'est ensuite déployée sur le périphérique virtuel Android.

.ios: ce dossier contient un projet Mac complet et est utilisé lorsque vous créez l'application Flutter
pour iOS. Il est similaire au dossier Android utilisé lors du développement d'une application pour
Android. Lorsque le code Flutter est compilé dans le code natif, il est injecté dans ce projet iOS, de
sorte que le résultat est une application iOS native. La création d'une application Flutter pour iOS
n'est possible que lorsque vous travaillez sur macOS.

.lib: C'est un dossier essentiel, qui représente la bibliothèque. C'est un dossier dans lequel nous
effectuerons nos 99% de travail de projet. Dans le dossier lib, nous trouverons les fichiers Dart qui
contiennent le code de notre application Flutter. Par défaut, ce dossier contient le fichier [Link],
qui est le fichier d'entrée de l'application Flutter.

.test: ce dossier contient un code Dart, qui est écrit pour que l'application Flutter effectue le test
automatisé lors de la création de l'application.

.gitignore: C'est un fichier texte contenant une liste de fichiers, d'extensions de fichiers et de
dossiers qui indique à Git quels fichiers doivent être ignorés dans un projet. Git est un fichier de
contrôle de version permettant de suivre les modifications du code source lors du développement
logiciel Git.

.metadata: il s'agit d'un fichier généré automatiquement par les outils Flutter, qui est utilisé pour
suivre les propriétés du projet Flutter. Ce fichier effectue les tâches internes, vous n'avez donc pas
besoin de modifier le contenu manuellement à tout moment.

.packages: il s'agit d'un fichier généré automatiquement par le SDK Flutter, qui est utilisé pour
contenir une liste de dépendances pour votre projet Flutter.
flutter_demoapp.iml: Il est toujours nommé en fonction du nom du projet Flutter qui contient des
paramètres supplémentaires du projet. Ce fichier exécute les tâches internes, qui sont gérées par le
SDK Flutter, vous n'avez donc pas besoin de modifier le contenu manuellement à tout moment.

[Link]: C'est le fichier de configuration du projet qui sera beaucoup utilisé lors de
l'utilisation du projet Flutter. Il vous permet de savoir comment fonctionne votre application. Ce
fichier contient:

• Paramètres généraux du projet tels que le nom, la description et la version du projet.


• Dépendances du projet.
• Actifs du projet (par exemple, images).

[Link]: C'est un fichier généré automatiquement basé sur le fichier .yaml. Il contient une
configuration plus détaillée sur toutes les dépendances.

[Link]: C'est un fichier généré automatiquement qui contient des informations sur le projet.
Nous pouvons éditer ce fichier si nous voulons partager des informations avec les développeurs.

Le fichier [Link] :

import 'package:flutter/[Link]';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {


// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Hello World Flutter Application',
theme: ThemeData(
// This is the theme of your application.
primarySwatch: [Link],
),
home: MyHomePage(title: 'Home page'),
);
}
}
class MyHomePage extends StatelessWidget {
MyHomePage({Key key, [Link]}) : super(key: key);
// This widget is the home page of your application.
final String title;

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text([Link]),
),
body: Center(
child: Text('Hello World'),
),
);
}
}

les résultat de ce code :

5. Le langage Dart
Dart est un langage de programmation open source, polyvalent et orienté objet avec une syntaxe de
style C développé par Google en 2011. Le but de la programmation Dart est de créer une interface
utilisateur frontale pour les applications Web et mobiles. Il est en cours de développement actif,
compilé en code machine natif pour la création d'applications mobiles, inspiré par d'autres langages
de programmation tels que Java, JavaScript, C # et est fortement typé. Puisque Dart est un langage
compilé, vous ne pouvez donc pas exécuter votre code directement; à la place, le compilateur
l'analyse et le transfère dans le code machine.

Il prend en charge la plupart des concepts courants des langages de programmation tels que les
classes, les interfaces, les fonctions, contrairement aux autres langages de programmation. Le
langage Dart ne prend pas en charge les tableaux directement. Il prend en charge la collection, qui
est utilisée pour répliquer la structure de données comme les tableaux, les génériques et le typage
facultatif.

Les variables :

Même dans un code Dart à sécurité de type, vous pouvez déclarer la plupart des variables sans
spécifier explicitement leur type à l'aide de var. Grâce à l'inférence de type, les types de ces
variables sont déterminés par leurs valeurs initiales :

var name = 'Voyager I';


var year = 1977;

var antennaDiameter = 3.7;

var flybyObjects = ['Jupiter', 'Saturn', 'Uranus', 'Neptune'];

var image = {

'tags': ['saturn'],

'url': '//path/to/[Link]'

};

const bar = 1000000; // Unit of pressure (dynes/cm2)

const double atm = 1.01325 * bar; // Standard atmosphere

int age = 20 ;

name = 'Bob'; // Without a type annotation

String nickname = 'Bobby';

Types intégrés (Buit-in)


Le langage Dart dispose d'un support spécial pour les types suivants :

• Nombres (int, double)


• Chaînes (String)
• Booléens (bool)
• Enregistrements ((valeur1, valeur2))
• Listes (List, également connues sous le nom de tableaux)
• Sets (Set)
• Maps (Carte)
• Runes (Runes ; souvent remplacées par les caractères API)
• Symboles (Symbol)
• La valeur null (Null)

Le langage Dart met en œuvre une sécurité saine et nulle.


La sécurité des variables nulles permet d'éviter une erreur résultant d'un accès involontaire à des
variables définies comme nulles. Cette erreur est appelée erreur de déréférencement de la valeur
nulle.

String? name // Nullable type. Can be `null` or string.

String name // Non-nullable type. Cannot be `null` but can be string.

Late variables :

Le modificateur late a deux cas d'utilisation :


• Déclarer une variable non annulable qui est initialisée après sa déclaration.
• Initialiser une variable paresseusement.

late String description;

void main() {
description = 'Feijoada!';
print(description);
}

Variables Finale :

Si vous n'avez jamais l'intention de modifier une variable, utilisez final ou const, soit à la place de
var, soit en plus d'un type. Une variable final ne peut être définie qu'une seule fois ; une variable
const est une constante à la compilation. (Les variables const sont implicitement finales).

final name = 'Bob'; // Without a type annotation


final String nickname = 'Bobby';

name = 'Alice'; // Error: a final variable can only be set once.

Les structures Alternatives et Itératives :

Les branches :

• les instructions et éléments if


• les instructions et expressions switch

if (isRaining()) {
[Link]();
} else if (isSnowing()) {
[Link]();
} else {
[Link]();
}

// switch case :

var command = 'OPEN';


switch (command) {
case 'CLOSED':
executeClosed();
case 'PENDING':
executePending();
case 'APPROVED':
executeApproved();
case 'DENIED':
executeDenied();
case 'OPEN':
executeOpen();
default:
executeUnknown();
}

Les boucles :
void main() {

for (int i = 0; i < 5; i++) {


print('hello ${i + 1}');
}

int j = 0 ;
while(j < 10){
print('hello ${j+ 1}');
j++ ;
}
}

Les Collections
Dart prend en charge les collections de listes, d'ensembles et de cartes. Pour en savoir plus sur la
configuration des types que contiennent les collections.

Listes : La collection la plus courante dans presque tous les langages de programmation est le
tableau, ou groupe ordonné d'objets. Dans Dart, les tableaux sont des objets List, et la plupart des
gens les appellent donc simplement des listes.

var list = [1, 2, 3];

var list = [
'Car',
'Boat',
'Plane',
];

var list = [1, 2, 3];


print(list);
print([Link] );
print(list[1]);
[Link](5);
list[1] = 1;
print(list[1]);

Sets :

Dans Dart, un ensemble est une collection non ordonnée d'éléments uniques. Le support Dart pour
les ensembles est fourni par les littéraux d'ensemble et le type Set.

var list = {1, 2, 3};


print(list);
print([Link] );
[Link](5);
[Link](3);
print(list);
[Link](1);
print(list);

Maps : En général, une map est un objet qui associe des clés et des valeurs. Les clés et les valeurs
peuvent être n'importe quel type d'objet. Chaque clé n'apparaît qu'une seule fois, mais vous pouvez
utiliser la même valeur plusieurs fois. La prise en charge des maps par Dart est assurée par les
littéraux de map et le type Map.

var nobleGases = {
2: 'helium',
10: 'neon',
18: 'argon',
};
[Link]((key, value) {
print([Link]() + " , "+ [Link]());
});

var gifts = Map<String, String>();


gifts['first'] = 'partridge';

gifts['second'] = 'turtledoves';

gifts['fifth'] = 'golden rings';

var nobleGases = Map<int, String>();

nobleGases[2] = 'helium';

nobleGases[10] = 'neon';

nobleGases[18] = 'argon';

Les Fonctions :

//Function declaration

num addNumbers(num a, num b) {


// Here, we use num as a type because it should work with int and double both.
return a + b;
}
var price1 = 29.99;
var price2 = 20.81;
var total = addNumbers(price1, price2);
var num1 = 10;
var num2 = 45;
var total2 = addNumbers(num1, num2);

isNoble(atomicNumber) {
return _nobleGases[atomicNumber] != null;

For functions that contain just one expression, you can use a shorthand syntax:

bool isNoble(int atomicNumber) => _nobleGases[atomicNumber] != null;

void enableFlags({bool? bold, bool? Hidden}) {…} // optional params

void enableFlags({bool bold = false, bool hidden = false}) {…} //value by default
Programmation orientée objet :
class Mobile {
//PropertyDeclaration
String color, brandName, modelName;

Mobile([Link], [Link], [Link]);

//MethodCreation
String calling() {
return "Mobilecandocalltoeveryone.";
}

String musicPlay() {
return "MobilecanplayalltypesofMusic.";
}

String clickPicture() {
return "Mobilecantakepictures.";
}
}

void main() {
//ObjectCreation
var myMob = new Mobile("Black", "AppleInc.", "iPhone11Pro");

//DisplayOutput
print([Link]);
print([Link]);
print([Link]);
print([Link]());
print([Link]());
print([Link]());
}

5.1. Dart et la programmation fonctionnelle

Impératif

Le paradigme impératif est un ensemble d'instructions que vous donnez à l'ordinateur. Vous donnez
les étapes détaillées de l'exécution d'un programme. Voyons cela à l'aide d'un exemple.

Énoncé du problème : Vous avez une liste de nombres et vous voulez trouver tous les nombres
pairs.
void main(List<String> args) {
final _result = [];
final _number = [1, 2, 3, 4, 5, 6, 7, 8];

for (int i in _number) {


if (i % 2 == 0) _result.add(i);
}
print(_result);
}

Déclaratif
Le paradigme déclaratif indique au programme ce qu'il veut. Il se concentre sur le "Quoi" plutôt que
sur le "Comment". Cela permet de rendre le code plus raisonnable.

Flutter est un Framework déclaratif.

void main(List<String> args) {


final _number = [1, 2, 3, 4, 5, 6, 7, 8];

final _result = _number.where((number) => number % 2 == 0).toList();

print(_result);
}

Maintenant, vous dites au programme ce que vous voulez. De plus, vous ne modifiez plus aucun
état.

Si nous comparons les deux extraits, vous observerez que pour l'impératif, nous devons parcourir la
boucle, l'exécuter mentalement en pensant à ce qu'elle fait, et ensuite nous comprenons le code. En
revanche, le code déclaratif ressemble à de la prose bien écrite (on peut encore l'améliorer en
convertissant number % 2 == 0 en une fonction isEven distincte).

Qu'est-ce que la programmation fonctionnelle ?

La programmation fonctionnelle (aka. FP ) est une manière déclarative d'écrire des programmes, où
un programme est composé de fonctions. Cette définition prendra tout son sens lorsque nous
aborderons certaines terminologies de la programmation fonctionnelle.

Fonctions de premier classe (HOF)

Dans Dart, les fonctions sont traitées comme des citoyens de première classe (First class function),
ce qui signifie que les fonctions sont traitées comme n'importe quelles autres valeurs telles que
String, int, bool, etc. On peut passer des fonctions comme arguments, les assigner à une variable et
renvoyer des fonctions comme résultat.

int add(int num1, int num2) => num1 + num2;

void main(List<String> args) {


final _add_number = add;
final result = _add_number(1, 2);
print(result);
}

bool isOddNumber(int x) {
return x % 2 != 0;
}

bool isEvenNumber(int x) {
return x % 2 == 0;
}

void show(Function fn) {


for (int i = 0; i < 10; i++) {
if (fn(i)) {
print(i);
}
}
}

void main() {
print("Even numbers:");
show(isEvenNumber);

print("Odd numbers:");
show(isOddNumber);
}

add(int x, int y) {
return x + y;
}

subtract(int x, int y) {
return x - y;
}

Function calculation(String op) {


if (op == '+') return add;
if (op == '-') return subtract;
return add;
}

void main() {
var fn = calculation('+');
print(fn(10, 20));

fn = calculation('-');
print(fn(30,20));
}
Fonctions d'ordre supérieur (HOF)
Une fonction qui prend une fonction comme argument ou qui renvoie une fonction est une fonction
d'ordre supérieur. Cela est possible parce que les fonctions sont traitées comme des citoyens de
première classe dans Dart.

Vous avez déjà utilisé des fonctions d'ordre supérieur si vous avez utilisé des méthodes de tableau
intégrées telles que where, map ou reduce.

Filtre(where) :
Le filtre prend une fonction prédicat et un tableau et renvoie une nouvelle liste contenant
uniquement les valeurs pour lesquelles la fonction prédicat renvoie vrai.

Imaginez que vous écriviez un programme pour filtrer tous les nombres pairs de la liste.

bool isOven(int number) => number % 2 == 0;


bool isOdden(int number) => !isOven(number);
void main(List<String> args) {
final _number = [1, 2, 3, 4, 5, 6, 7, 8];

final _result_odd = _number.where((element) => isOdden(element));


print(_result_odd);

final _result_ov = _number.where((element) => isOven(element));

print(_result_ov);
}

Map :
La Map fonctionne de la même manière qu'un filtre, sauf qu'au lieu de prendre une fonction
prédicat, elle prend une fonction mappeur, l'applique à chaque élément de la liste et renvoie une
nouvelle liste.

Imaginez que vous écriviez un programme pour doubler tous les éléments de la liste.

void main(List<String> args) {


final _number = [1, 2, 3, 4, 5, 6, 7, 8];

final result = _number.map((e) => e * 2).toList();

print(result);
}

Réduire :
Elle réduit une collection en une seule valeur en combinant tous les éléments à l'aide de la fonction
passée.

Écrivons un programme qui renvoie la somme de tous les nombres de la collection.

void main(List<String> args) {


final _number = [1, 2, 3, 4, 5, 6, 7, 8];

final result = _number.reduce((value, element) => value + element);

print(result);
}

Pourquoi se donner la peine d'apprendre FP ?


Avant d'aborder les aspects techniques, je tiens à souligner que l'apprentissage de FP vous fait
penser d'une manière différente. Pour moi, c'était comme un exercice pour mon cerveau. Je pense
que cela m'a aidé à améliorer mes compétences en matière de développement et ma façon d'aborder
les problèmes.

• Il est plus facile de raisonner sur le code. Le code devient plus concis et plus expressif. Un
code raisonnable est plus facile à maintenir.
• Il favorise la modularité et est hautement composable.
• Il divise le problème en petits morceaux.
• Il aide à augmenter les performances par des exécutions parallèles, la mémoïsation et
d'autres techniques (que nous allons couvrir).
• Il est plus facile d'écrire des tests et facilite le débogage.

6. Les Bases de Flutter

6.1. Les widgets Flutter


Chaque fois que vous allez coder pour créer quoi que ce soit dans Flutter, ce sera à l'intérieur d'un
widget. L'objectif principal est de créer l'application à partir de widgets. Il décrit à quoi devrait
ressembler la vue de votre application avec sa configuration et son état actuels. Lorsque vous avez
apporté une modification au code, le widget reconstruit sa description en calculant la différence
entre le widget précédent et actuel pour déterminer les modifications minimales pour le rendu dans
l'interface utilisateur de l'application.

Les widgets sont imbriqués les uns avec les autres pour créer l'application. Cela signifie que la
racine de votre application est elle-même un widget, et tout en bas est également un widget. Par
exemple, un widget peut afficher quelque chose, définir le design, gérer l'interaction, etc.

L'image ci-dessous est une représentation visuelle simple de l'arborescence des widgets.
Classe de conteneur dans Flutter
La classe Container de Flutter est un widget de commodité qui combine les fonctions courantes de
peinture, de positionnement et de dimensionnement des widgets. Une classe Container peut être
utilisée pour stocker un ou plusieurs widgets et les positionner sur l'écran à notre convenance.
Fondamentalement, un conteneur est comme une boîte dans laquelle on stocke du contenu. Un
élément de conteneur de base qui stocke un widget possède une marge, qui sépare le conteneur
actuel des autres contenus. L'ensemble du conteneur peut être entouré d'une bordure de différentes
formes, par exemple des rectangles arrondis, etc. Un conteneur entoure son enfant avec un
rembourrage et applique ensuite des contraintes supplémentaires à l'étendue du rembourrage (en
incorporant la largeur et la hauteur en tant que contraintes, si l'une ou l'autre n'est pas nulle).

Classe de Scaffold dans Flutter


Scaffold est une classe dans Flutter qui fournit de nombreux widgets ou nous pouvons dire APIs
comme Drawer, Snack-Bar, Bottom-Navigation-Bar, Floating-Action-Button, App-Bar, etc.
L'échafaudage s'étend ou occupe tout l'écran de l'appareil. Il occupe l'espace disponible.
L'échafaudage fournira un cadre pour mettre en œuvre la conception matérielle de base de
l'application.

Widget build(BuildContext context)


{
return Scaffold(
appBar: AppBar(
title: const Text('GeeksforGeeks'),
),

Classe de MaterialApp dans Flutter :


Classe MaterialApp : MaterialApp est une classe prédéfinie ou un widget dans une application
Flutter. Il s'agit probablement du composant principal d'une application Flutter. Le widget
MaterialApp fournit une enveloppe autour d'autres Widgets Material. Nous pouvons accéder à tous
les autres composants et widgets fournis par le SDK Flutter. Les widgets Text, DropdownButton,
AppBar, Scaffold, ListView, StatelessWidget, StatefulWidget, IconButton, TextField, Padding,
ThemeData, etc. sont des widgets accessibles via la classe MaterialApp. Il existe de nombreux
autres widgets accessibles à l'aide de la classe MaterialApp. En utilisant ce widget, nous pouvons
créer une application attrayante qui suit les lignes directrices du Material Design.
Voici le constructeur de la classe MaterialApp :

import 'package:flutter/[Link]';

void main() {
runApp(const GFGapp());
}

class GFGapp extends StatelessWidget {


const GFGapp({Key? key}) : super(key: key);

@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'GeeksforGeeks',
theme: ThemeData(primarySwatch: [Link]),
darkTheme: ThemeData(primarySwatch: [Link]),
color: [Link],
supportedLocales: {const Locale('en', ' ')},
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(title: const Text('GeeksforGeeks')),
),
);
}
}

Classe de Drawer dans Flutter :


Le widget Drawer est utilisé pour donner accès aux différentes destinations et fonctionnalités de
votre application. Il est représenté par trois lignes horizontales parallèles à l'extrémité supérieure de
l'échafaudage. Il possède un mouvement horizontal à partir du bord de l'échafaudage qui permet de
naviguer vers différents itinéraires dans l'application Flutter.

Afin d'utiliser le tiroir d'application, vous devez importer le paquet de composants matériels qui est
"package : flutter/[Link]".
L'AppDrawer de navigation est divisé en trois sections : l'en-tête, le corps et le pied de page. L'idée
est d'avoir un navigateur avec quelques éléments en tant qu'enfants du tiroir qui seront dirigés vers
différentes destinations lorsqu'on les touchera. Tous les enfants d'un widget Drawer sont
généralement dans un ListView et, initialement, seul le DrawerHeader est présent dans l'interface
utilisateur qui s'étend horizontalement lorsqu'on le touche.

import 'package:flutter/[Link]';

// function to trigger app build


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

class MyApp extends StatelessWidget {


final appTitle = 'Flutter Drawer Demo';

const MyApp({Key? key}) : super(key: key);

@override
Widget build(BuildContext context) {
return MaterialApp(
title: appTitle,
home: MyHomePage(title: appTitle),
); // MaterialApp
}
}

class MyHomePage extends StatelessWidget {


final String title;

const MyHomePage({Key? key, required [Link]}) : super(key: key);

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(title),
backgroundColor: [Link],
),
body: const Center(
child: Text(
'A drawer is an invisible side screen.',
style: TextStyle(fontSize: 20.0),
)),
drawer: Drawer(
child: ListView(
padding: const [Link](0),
children: [
const DrawerHeader(
decoration: BoxDecoration(
color: [Link],
), //BoxDecoration
child: UserAccountsDrawerHeader(
decoration: BoxDecoration(color: [Link]),
accountName: Text(
"Abhishek Mishra",
style: TextStyle(fontSize: 18),
),
accountEmail: Text("abhishekm977@[Link]"),
currentAccountPictureSize: [Link](50),
currentAccountPicture: CircleAvatar(
backgroundColor: [Link](255, 165, 255, 137),
child: Text(
"A",
style: TextStyle(fontSize: 30.0, color: [Link]),
), //Text
), //circleAvatar
), //UserAccountDrawerHeader
), //DrawerHeader
ListTile(
leading: const Icon([Link]),
title: const Text(' My Profile '),
onTap: () {
[Link](context);
},
),
ListTile(
leading: const Icon([Link]),
title: const Text(' My Course '),
onTap: () {
[Link](context);
},
),
ListTile(
leading: const Icon(Icons.workspace_premium),
title: const Text(' Go Premium '),
onTap: () {
[Link](context);
},
),
ListTile(
leading: const Icon(Icons.video_label),
title: const Text(' Saved Videos '),
onTap: () {
[Link](context);
},
),
ListTile(
leading: const Icon([Link]),
title: const Text(' Edit Profile '),
onTap: () {
[Link](context);
},
),
ListTile(
leading: const Icon([Link]),
title: const Text('LogOut'),
onTap: () {
[Link](context);
},
),
],
),
), //Drawer
);
}
}

Classe de AppBar dans Flutter :

AppBar est généralement le composant le plus haut de l'application (ou parfois le plus bas), il
contient la barre d'outils et d'autres boutons d'action communs. Comme tous les composants d'une
application Flutter sont des widgets ou des combinaisons de widgets, l'AppBar est également une
classe ou un widget intégré dans Flutter. AppBar est donc également une classe intégrée ou un
widget dans Flutter qui donne la fonctionnalité de l'AppBar dès le départ. Le widget AppBar est
basé sur le Material Design et la plupart des informations sont déjà fournies par d'autres classes
comme MediaQuery, Scaffold, quant à l'endroit où le contenu de l'AppBar doit être placé. Bien que
la classe AppBar soit très flexible et puisse être facilement personnalisée, nous pouvons également
utiliser le widget SliverAppBar qui donne une fonctionnalité de défilement à la barre d'application.
Nous pouvons également créer notre propre barre d'application personnalisée à partir de zéro.

import 'package:flutter/[Link]';

void main() {
runApp(gfgApp()); //MaterialApp
}

MaterialApp gfgApp() {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('GeeksforGeeks'),
), //AppBar
body: const Center(
child: Text(
'GeeksforGeeks',
style: TextStyle(fontSize: 24),
), //Text
), // center
), //Scaffold
debugShowCheckedModeBanner: false, //Removing Debug Banner
);
}

Types de widget

Nous pouvons diviser le widget Flutter en deux catégories:

• Visible (sortie et entrée)


• Invisible (mise en page et contrôle)

Widget visible :

Les widgets visibles sont liés aux données d'entrée et de sortie de l'utilisateur. Certains des types
importants de ce widget sont:

Text :
Un widget Texte contient du texte à afficher à l'écran. Nous pouvons aligner le widget de texte en
utilisant la propriété textAlign, et la propriété style permet la personnalisation du texte qui inclut la
police, l'épaisseur de la police, le style de police, l'espacement des lettres, la couleur et bien d'autres.
Nous pouvons l'utiliser comme ci-dessous des extraits de code.

new Text(

'Hello, Javatpoint!',
textAlign: [Link],
style: new TextStyle(fontWeight: [Link]),
)

TextField
TextField et TextFormField sont les deux widgets les plus courants pour obtenir les commentaires
de l'utilisateur. Ils peuvent être utilisés pour créer des formulaires, des pages de connexion, etc. Afin
de rendre leur mise en œuvre efficace et précise, nous devons ajouter certaines fonctionnalités.

Declaration de varable _b
num _b ; au niveau de la class
TextField(
decoration: const InputDecoration(labelText: 'Number b :'),
keyboardType: [Link],
onChanged: (value){
setState(() {
_b = [Link](value) ;
});
},

Button:
Ce widget vous permet d'effectuer une action au clic. Flutter ne vous permet pas d'utiliser
directement le widget Button; à la place, il utilise un type de boutons comme un FlatButton et un
RaisedButton. Nous pouvons l'utiliser comme ci-dessous des extraits de code.
//FlatButton Example

new FlatButton(
child: Text("Click here"),
onPressed: () {
// Do something here
},
),

//RaisedButton Example
new RaisedButton(
child: Text("Click here"),
elevation: 5.0,
onPressed: () {
// Do something here
},
),

Dans l'exemple ci-dessus, la propriété onPressed nous permet d'effectuer une action lorsque vous
cliquez sur le bouton, et la propriété d'élévation est utilisée pour changer la façon dont elle se
démarque.

Image :
Ce widget contient l'image qui peut la récupérer à partir de plusieurs sources, telles que le dossier
d'actifs ou directement à partir de l'URL. Il fournit de nombreux constructeurs pour charger l'image,
qui sont donnés ci-dessous:

• Image: Il s'agit d'un chargeur d'image générique, utilisé par ImageProvider.


• actif: il charge l'image à partir du dossier d'actifs de votre projet.
• file: Il charge les images du dossier système.
• mémoire: il charge l'image de la mémoire.
• réseau: Il charge les images du réseau.

Pour ajouter une image dans le projet, vous devez d'abord créer un dossier de ressources dans lequel
vous stockez vos images, puis ajouter la ligne ci-dessous dans le fichier [Link].

assets:

- assets/

[Link]('assets/[Link]')

Widget invisible
Les widgets invisibles sont liés à la disposition et au contrôle des widgets. Il permet de contrôler le
comportement réel des widgets et leur apparence à l'écran. Certains des types importants de ces
widgets sont:

Column :

Un widget de colonne est un type de widget qui organise tous les widgets de ses enfants dans un
alignement vertical. Il fournit un espacement entre les widgets à l'aide des propriétés
mainAxisAlignment et crossAxisAlignment. Dans ces propriétés, l'axe principal est l'axe vertical et
l'axe transversal est l'axe horizontal.

new Column(

mainAxisAlignment: [Link],
children: <Widget>[
new Text(
"VegElement",
),
new Text(
"Non-vegElement"
),
],
),

Ligne « Row » :

Le widget de ligne est similaire au widget de colonne, mais il construit un widget horizontalement
plutôt que verticalement. Ici, l'axe principal est l'axe horizontal et l'axe transversal est l'axe vertical.

new Row(

mainAxisAlignment: [Link],
children: <Widget>[
new Text(
"VegElement",
),
new Text(
"Non-vegElement"
),
],
),
Center :

Ce widget est utilisé pour centrer le widget enfant, qui vient à l'intérieur. Tous les exemples
précédents contiennent à l'intérieur du widget central.

Center(

child: new clumn(


mainAxisAlignment: [Link],
children: <Widget>[
new Text(
"VegElement",
),
new Text(
"Non-vegElement"
),
],
),
),

Padding :

Ce widget enveloppe les autres widgets pour leur donner un remplissage dans des directions
spécifiées. Vous pouvez également fournir un rembourrage dans toutes les directions. Nous pouvons
le comprendre à partir de l'exemple ci-dessous qui donne au widget texte un remplissage de 6.0
dans toutes les directions.

Padding(

padding: const [Link](6.0),


child: new Text( "Element 1", ),
),

Stack :

C'est un widget essentiel, qui est principalement utilisé pour superposer un widget, comme un
bouton sur un dégradé d'arrière-plan.

Widget de gestion d'état


Dans Flutter, il existe principalement deux types de widgets:

• StatelessWidget
• StatefulWidget

StatefulWidget
Un StatefulWidget a des informations d'état. Il contient principalement deux classes: l'objet d'état et
le widget. Il est dynamique car il peut modifier les données internes pendant la durée de vie du
widget. Ce widget n'a pas de méthode build (). Il a la méthode createState (), qui retourne une classe
qui étend la classe d'état Flutters. Les exemples de StatefulWidget sont Checkbox, Radio, Slider,
InkWell, Form et TextField.

class Car extends StatefulWidget {

const Car({ Key key, [Link] }) : super(key: key);

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

class _CarState extends State<Car> {


@override
Widget build(BuildContext context) {
return Container(
color: const Color(0xFEEFE),
child: Container(
child: Container( //child: Container() )
)
);
}
}

StatelessWidget :

Le StatelessWidget ne dispose d'aucune information d'état. Il reste statique tout au long de son cycle
de vie. Les exemples du StatelessWidget sont Text, Row, Column, Container, etc.

class MyStatelessCarWidget extends StatelessWidget {

const MyStatelessCarWidget ({ Key key }) : super(key: key);

@override
Widget build(BuildContext context) {
return Container(color: const Color(0x0xFEEFE));
}
}

6.2. Disposition Flutter « Layout »


Le concept principal du mécanisme de mise en page est le widget. Nous savons que le flutter
assume tout comme un widget. Ainsi, l'image, l'icône, le texte et même la mise en page de votre
application sont tous des widgets. Ici, certaines des choses que vous ne voyez pas sur l'interface
utilisateur de votre application, telles que les lignes, les colonnes et les grilles qui organisent,
contraignent et alignent les widgets visibles sont également les widgets.

Dans l'image ci-dessus, le conteneur est une classe de widget qui nous permet de personnaliser le
widget enfant. Il est principalement utilisé pour ajouter des bordures, un remplissage, des marges,
une couleur d'arrière-plan et bien d'autres. Ici, le widget texte vient sous le conteneur pour ajouter
des marges. La ligne entière est également placée dans un conteneur pour ajouter une marge et un
remplissage autour de la ligne. En outre, le reste de l'interface utilisateur est contrôlé par des
propriétés telles que la couleur, le [Link], etc.

Types de widgets de mise en page


Nous pouvons classer le widget de mise en page en deux types:

• Widget enfant unique


• Widget enfant multiple

Widgets enfant unique :

Le widget de mise en page enfant unique est un type de widget, qui ne peut avoir qu'un seul widget
enfant à l'intérieur du widget de mise en page parent. Ces widgets peuvent également contenir des
fonctionnalités de mise en page spéciales. Flutter nous fournit de nombreux widgets pour enfant
unique pour rendre l'interface utilisateur de l'application attrayante. Si nous utilisons ces widgets de
manière appropriée, cela peut nous faire gagner du temps et rendre le code de l'application plus
lisible. La liste des différents types de widgets enfant unique est:

Container : c'est le widget de mise en page le plus populaire qui fournit des options personnalisables
pour la peinture, le positionnement et le dimensionnement des widgets.

Center(

child: Container(
margin: const [Link](15.0),
color: [Link],
width: 42.0,
height: 42.0,
),
)

Padding : C'est un widget qui est utilisé pour organiser son widget enfant par le remplissage donné.
Il contient EdgeInsets et [Link] pour le côté souhaité où vous souhaitez fournir un
remplissage.

const Greetings(

child: Padding(
padding: [Link](14.0),
child: Text('Hello JavaTpoint!'),
),
)

Center: ce widget vous permet de centrer le widget enfant en lui-même.

Align : il s'agit d'un widget, qui aligne son widget enfant en lui-même et le dimensionne en fonction
de la taille de l'enfant. Il offre plus de contrôle pour placer le widget enfant à la position exacte où
vous en avez besoin.
Center(

child: Container(
height: 110.0,
width: 110.0,
color: [Link],
child: Align(
alignment: [Link],
child: FlutterLogo(
size: 50,
),
),
),
)

SizedBox: Ce widget vous permet de donner la taille spécifiée au widget enfant à travers tous les
écrans.

SizedBox(

width: 300.0,
height: 450.0,
child: const Card(child: Text('Hello JavaTpoint!')),
)

FittedBox: il met à l'échelle et positionne le widget enfant en fonction de l'ajustement spécifié.

import 'package:flutter/[Link]';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {


// It is the root widget of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Multiple Layout Widget',
debugShowCheckedModeBanner: false,
theme: ThemeData(
// This is the theme of your application.
primarySwatch: [Link],
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("FittedBox Widget")),
body: Center(
child: FittedBox(child: Row(
children: <Widget>[
Container(

child: [Link]('assets/[Link]'),
),
Container(
child: Text("This is a widget"),
)
],
),
fit: [Link],
)
),
);
}
}

Plusieurs widgets enfants :

Les widgets enfants multiples sont un type de widget, qui contient plusieurs widgets enfants, et la
disposition de ces widgets est unique. Par exemple, le widget Row disposant de son widget enfant
dans une direction horizontale, et le widget Column disposant de son widget enfant dans une
direction verticale. Si nous combinons le widget Ligne et Colonne, alors il peut construire n'importe
quel niveau du widget complexe.

Row: Il permet d'organiser ses widgets enfants dans une direction horizontale.

import 'package:flutter/[Link]';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {


// It is the root widget of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Multiple Layout Widget',
debugShowCheckedModeBanner: false,
theme: ThemeData(
// This is the theme of your application.
primarySwatch: [Link],
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Center(
child: Container(
alignment: [Link],
color: [Link],
child: Row(
children: <Widget>[
Expanded(
child: Text('Peter', textAlign: [Link]),
),
Expanded(
child: Text('John', textAlign: [Link] ),

),
Expanded(
child: FittedBox(
fit: [Link], // otherwise the logo will be tiny
child: const FlutterLogo(),
),
),
],
),
),
);
}
}

Column: Elle permet d'organiser ses widgets enfants dans une direction verticale.

ListView: C'est le widget de défilement le plus populaire qui nous permet d'organiser ses widgets
enfants les uns après les autres dans le sens du défilement.

GridView: Il nous permet d'organiser ses widgets enfants sous la forme d'un tableau 2D déroulant
de widgets. Il se compose d'un motif répété de cellules disposées dans une disposition horizontale et
verticale.

Expanded: Il permet de faire en sorte que les enfants d'un widget Ligne et Colonne occupent le
maximum de surface possible.

Table: C'est un widget qui nous permet d'organiser ses enfants dans un widget basé sur une table.

Flow: Cela nous permet d'implémenter le widget basé sur le flux.

Stack : C'est un widget essentiel, qui est principalement utilisé pour superposer plusieurs widgets
enfants. Il vous permet de mettre en place les multiples couches sur l'écran. L'exemple suivant aide
à le comprendre.

import 'package:flutter/[Link]';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {


// It is the root widget of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Multiple Layout Widget',
debugShowCheckedModeBanner: false,
theme: ThemeData(
// This is the theme of your application.
primarySwatch: [Link],
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Center(
child: Container(
alignment: [Link],
color: [Link],
child: Stack(
children: <Widget>[
// Max Size
Container(
color: [Link],
),
Container(
color: [Link],
height: 400.0,
width: 300.0,
),
Container(
color: [Link],
height: 220.0,
width: 200.0,
)
],
),
),
);
}
}

Disposition du complexe du mise en page :


Dans cette section, nous allons apprendre comment vous pouvez créer une interface utilisateur
complexe en utilisant à la fois des widgets de mise en page enfants simples et multiples. Le cadre de
mise en page vous permet de créer une mise en page d'interface utilisateur complexe en imbriquant
les lignes et les colonnes à l'intérieur des lignes et des colonnes.

Voyons un exemple d'interface utilisateur complexe en créant la liste de produits. Pour cela, vous
devez d'abord remplacer le code du fichier [Link] par l'extrait de code suivant.

import 'package:flutter/[Link]';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {


// It is the root widget of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo Application', theme: ThemeData(
primarySwatch: [Link],),
home: MyHomePage(title: 'Complex layout example'),
);
}
}
class MyHomePage extends StatelessWidget {
MyHomePage({Key key, [Link]}) : super(key: key);
final String title;

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Product List")),
body: ListView(
padding: const [Link](3.0, 12.0, 3.0, 12.0),
children: <Widget>[
ProductBox(
name: "iPhone",
description: "iPhone is the top branded phone ever",
price: 55000,
image: "[Link]"
),
ProductBox(
name: "Android",
description: "Android is a very stylish phone",
price: 10000,
image: "[Link]"
),
ProductBox(
name: "Tablet",
description: "Tablet is a popular device for official meetings",
price: 25000,
image: "[Link]"
),
ProductBox(
name: "Laptop",
description: "Laptop is most famous electronic device",
price: 35000,
image: "[Link]"
),
ProductBox(
name: "Desktop",
description: "Desktop is most popular for regular use",
price: 10000,
image: "[Link]"
),
],
)
);
}
}
class ProductBox extends StatelessWidget {
ProductBox({Key key, [Link], [Link], [Link], [Link]}) :
super(key: key);
final String name;
final String description;
final int price;
final String image;

Widget build(BuildContext context) {


return Container(
padding: [Link](2),
height: 110,
child: Card(
child: Row(
mainAxisAlignment: [Link],
children: <Widget>[
[Link]("assets/" + image),
Expanded(
child: Container(
padding: [Link](5),
child: Column(
mainAxisAlignment: [Link],
children: <Widget>[
Text(
[Link], style: TextStyle(
fontWeight: [Link]
)
),
Text([Link]), Text(
"Price: " + [Link]()
),
],
)
)
)
]
)
)
);
}
}

Dans le code ci-dessus, nous créons le widget ProductBox qui contient les détails du produit, tels
que l'image, le nom, le prix et la description. Dans le widget ProductBox, nous utilisons les widgets
enfants suivants: Conteneur, Ligne, Colonne, Développé, Carte, Texte, Image, etc. Ce widget
contient la mise en page suivante:

6.3. Les gestes

Les gestes sont une fonctionnalité intéressante de Flutter qui nous permet d'interagir avec
l'application mobile (ou tout appareil tactile). D'une manière générale, les gestes définissent toute
action physique ou mouvement d'un utilisateur dans l'intention d'un contrôle spécifique de l'appareil
mobile. Certains des exemples de gestes sont:

• Lorsque l'écran du mobile est verrouillé, vous faites glisser votre doigt sur l'écran pour le
déverrouiller.
• En appuyant sur un bouton sur l'écran de votre mobile
• Appuyez et maintenez une icône d'application sur un appareil tactile pour la faire glisser sur
les écrans.
Nous utilisons tous ces gestes dans la vie de tous les jours pour interagir avec votre téléphone ou
appareil tactile.

Flutter divise le système gestuel en deux couches différentes, qui sont données ci-dessous:

• Pointeurs
• Gestes

Les Pointeurs :

Les pointeurs sont la première couche qui représente les données brutes sur l'interaction de
l'utilisateur. Il contient des événements qui décrivent l'emplacement et le mouvement des pointeurs
tels que les touches, les souris et le style sur les écrans. Flutter ne fournit aucun mécanisme pour
annuler ou arrêter les événements de pointeur d'être distribués davantage. Flutter fournit un widget
Listener pour écouter les événements de pointeur directement à partir de la couche de widgets. Les
événements-pointeurs sont des catégories en quatre types principaux:

• PointerDownEvents
• PointerMoveEvents
• PointerUpEvents
• PointeurAnnulerEvénements

PointerDownEvents: Il permet au pointeur de contacter l'écran à un endroit particulier.

PointerMoveEvents: Il permet au pointeur de se déplacer d'un emplacement à un autre sur l'écran.

PointerUpEvents: Il permet au pointeur d'arrêter de contacter l'écran.

PointerCancelEvents: cet événement est envoyé lorsque l'interaction du pointeur est annulée.

Les Gestes :

C'est la deuxième couche qui représente les actions sémantiques telles que toucher, glisser et mettre
à l'échelle, qui sont reconnues à partir de plusieurs événements de pointeur individuels. Il est
également capable de distribuer plusieurs événements correspondant au cycle de vie des gestes tels
que le début du glissement, le glissement de la mise à jour et le glissement de la fin. Certains des
gestes couramment utilisés sont répertoriés ci-dessous:

Tap : Cela signifie toucher la surface de l'écran du bout du doigt pendant une courte période, puis
les relâcher. Ce geste contient les événements suivants:

• onTapDown
• onTapUp
• onTap
• onTapCancel

Double Tap: Cela ressemble à un geste Tap, mais vous devez appuyer deux fois en peu de temps. Ce
geste contient les événements suivants:

• onDoubleTap
Glisser: Cela nous permet de toucher la surface de l'écran avec un doigt et de le déplacer d'un
endroit à un autre, puis de les relâcher. Flutter classe le glissement en deux types:

Glissement horizontal: ce geste permet au pointeur de se déplacer horizontalement. Il contient les


événements suivants:
• onHorizontalDragStart
• onHorizontalDragUpdate
• onHorizontalDragEnd

Glissement vertical: ce geste permet au pointeur de se déplacer dans une direction verticale. Il
contient les événements suivants:
• onVerticalDragStart
• onVerticalDragStart
• onVerticalDragStart

Appui long: cela signifie toucher la surface de l'écran à un endroit particulier pendant une longue
période. Ce geste contient les événements suivants:

• onLongPress

Pan: Cela signifie toucher la surface de l'écran avec un doigt, qui peut se déplacer dans n'importe
quelle direction sans relâcher le bout du doigt. Ce geste contient les événements suivants:

• onPanStart
• onPanUpdate
• onPanEnd

Pinch: Cela signifie pincer (déplacer son doigt et son pouce ou les rapprocher sur un écran tactile) la
surface de l'écran à l'aide de deux doigts pour effectuer un zoom avant ou arrière sur un écran.

Détecteur de gestes :

import 'package:flutter/[Link]';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {


// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo Application', theme: ThemeData(
primarySwatch: [Link],),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
MyHomePageState createState() => new MyHomePageState();
}

class MyHomePageState extends State<MyHomePage> {


@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text('Gestures Example'),
centerTitle: true,
),
body: new Center(child: GestureDetector(
onTap: () {
print('Box Clicked');
},
child: Container(
height: 60.0,
width: 120.0,
padding: [Link](10.0),
decoration: BoxDecoration(
color: [Link],
borderRadius: [Link](15.0),
),
child: Center(child: Text('Click Me')),
)
)),
);
}
}

Exemple de gestes multiples :

import 'package:flutter/[Link]';

import 'package:flutter/[Link]';

//It is the entry point for your Flutter app.


void main() {
runApp(
MaterialApp(
title: 'Multiple Gestures Demo',
home: Scaffold(
appBar: AppBar(
title: Text('Multiple Gestures Demo'),
),
body: DemoApp(),
),
),
);
}

class DemoApp extends StatelessWidget {


@override
Widget build(BuildContext context) {
return RawGestureDetector(
gestures: {
AllowMultipleGestureRecognizer: GestureRecognizerFactoryWithHandlers<
AllowMultipleGestureRecognizer>(
() => AllowMultipleGestureRecognizer(),
(AllowMultipleGestureRecognizer instance) {
[Link] = () => print('It is the parent container gesture');
},
)
},
behavior: [Link],
//Parent Container
child: Container(
color: [Link],
child: Center(
//Now, wraps the second container in RawGestureDetector
child: RawGestureDetector(
gestures: {
AllowMultipleGestureRecognizer:
GestureRecognizerFactoryWithHandlers<
AllowMultipleGestureRecognizer>(
() => AllowMultipleGestureRecognizer(), //constructor
(AllowMultipleGestureRecognizer instance) { //initializer
[Link] = () => print('It is the nested container');
},
)
},
//Creates the nested container within the first.
child: Container(
color: [Link],
width: 250.0,
height: 350.0,
),
),
),
),
);
}
}

class AllowMultipleGestureRecognizer extends TapGestureRecognizer {


@override
void rejectGesture(int pointer) {
acceptGesture(pointer);
}
}

8. Routage avec Fultter


La navigation et le routage sont quelques-uns des concepts de base de toutes les applications
mobiles, qui permettent à l'utilisateur de se déplacer entre différentes pages. Nous savons que
chaque application mobile contient plusieurs écrans permettant d'afficher différents types
d'informations. Par exemple, une application peut avoir un écran contenant divers produits. Lorsque
l'utilisateur appuie sur ce produit, il affiche immédiatement des informations détaillées sur ce
produit.

Dans Flutter, les écrans et les pages sont appelés itinéraires, et ces itinéraires ne sont qu'un widget.
Sous Android, un itinéraire est similaire à une activité, alors que, sous iOS, il équivaut à un
ViewController.

Dans toute application mobile, la navigation vers différentes pages définit le flux de travail de
l'application et la manière de gérer la navigation est appelée routage. Flutter fournit une classe de
routage de base MaterialPageRoute et deux méthodes [Link] () et [Link] () qui
montrent comment naviguer entre deux routes. Les étapes suivantes sont nécessaires pour démarrer
la navigation dans votre application.

import 'package:flutter/[Link]';

void main() {
runApp(MaterialApp(
title: 'Flutter Navigation',
theme: ThemeData(
// This is the theme of your application.
primarySwatch: [Link],
),
home: FirstRoute(),
));
}

class FirstRoute extends StatelessWidget {


@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('First Screen'),
),
body: Center(
child: RaisedButton(
child: Text('Click Here'),
color: [Link],
onPressed: () {
[Link](
context,
MaterialPageRoute(builder: (context) => SecondRoute()),
);
},
),
),
);
}
}

class SecondRoute extends StatelessWidget {


@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Second Screen"),
),
body: Center(
child: RaisedButton(
color: [Link],
onPressed: () {
[Link](context);
},
child: Text('Go back'),
),
),
);
}
}
Navigation avec des itinéraires nommés

import 'package:flutter/[Link]';

void main() {
runApp( MaterialApp(
title: 'Named Route Navigation',
theme: ThemeData(
// This is the theme of your application.
primarySwatch: [Link],
),
// Start the app with the "/" named route. In this case, the app starts
// on the FirstScreen widget.
initialRoute: '/',
routes: {
// When navigating to the "/" route, build the FirstScreen widget.
'/': (context) => HomeScreen(),
// When navigating to the "/second" route, build the SecondScreen widget.
'/second': (context) => SecondScreen(),
},
));
}

class HomeScreen extends StatelessWidget {


@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Home Screen'),
),
body: Center(
child: RaisedButton(
child: Text('Click Here'),
color: [Link],
onPressed: () {
[Link](context, '/second');
},
),
),
);
}
}

class SecondScreen extends StatelessWidget {


@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Second Screen"),
),
body: Center(
child: RaisedButton(
color: [Link],
onPressed: () {
[Link](context);
},
child: Text('Go back!'),
),
),
);
}
}

9. Flutter et Sqlite :

Si vous écrivez une application qui doit persister et interroger de grandes quantités de données sur
l'appareil local, envisagez d'utiliser une base de données au lieu d'un fichier local ou d'un magasin
de valeurs clés. En général, les bases de données permettent des insertions, des mises à jour et des
requêtes plus rapides que les autres solutions de persistance locales.

Les applications Flutter peuvent utiliser les bases de données SQLite via le plugin sqflite disponible
sur [Link]. Cette recette démontre les bases de l'utilisation de sqflite pour insérer, lire, mettre à
jour et supprimer des données sur divers objets.

Pour travailler avec des bases de données SQLite, importez les paquets sqflite et path.

Le paquet sqflite fournit des classes et des fonctions permettant d'interagir avec une base de
données SQLite.
Le paquet path fournit des fonctions permettant de définir l'emplacement de stockage de la base de
données sur le disque.

flutter pub add sqflite path

Note s : Pour installer sqlite_common_ffi_web (Sqlite Facotory pour le web):


[Link]
binaries (Version web sqlite).

import 'dart:async';

import 'package:flutter/[Link]';
import 'package:path/[Link]';
import 'package:sqflite/[Link]';

Définir le modèle de données :

class Personne {
final int id;
final String name;
final int age;

const Dog({
required [Link],
required [Link],
required [Link],
});
}

Ouvrir la base de données :

// Avoid errors caused by flutter upgrade.


// Importing 'package:flutter/[Link]' is required.
[Link]();
// Open the database and store the reference.
final database = openDatabase(
// Set the path to the database. Note: Using the `join` function from the
// `path` package is best practice to ensure the path is correctly
// constructed for each platform.
join(await getDatabasesPath(), 'personne_database.db'),
);

Créer le tableau des personnes :


Ensuite, créez une table pour stocker des informations sur les différents chiens. Pour cet exemple,
créez une table appelée "chiens" qui définit les données pouvant être stockées. Chaque personne
contient un identifiant, un nom et un âge. Ceux-ci sont donc représentés par trois colonnes dans la
table Personnes.

• L'id est un int Dart, et est stocké en tant que type de données SQLite INTEGER. Il est
également conseillé d'utiliser l'identifiant comme clé primaire de la table afin d'améliorer les
temps de requête et de mise à jour.
• Le nom est une chaîne Dart et est stocké sous la forme d'un type de données TEXT SQLite.
• L'âge est également un Dart int, et est stocké sous la forme d'un type de données INTEGER.

final database = openDatabase(


// Set the path to the database. Note: Using the `join` function from the
// `path` package is best practice to ensure the path is correctly
// constructed for each platform.
join(await getDatabasesPath(), 'personne_database.db'),
// When the database is first created, create a table to store dogs.
onCreate: (db, version) {
// Run the CREATE TABLE statement on the database.
return [Link](
'CREATE TABLE personne(id INTEGER PRIMARY KEY, name TEXT, age INTEGER)',
);
},
// Set the version. This executes the onCreate function and provides a
// path to perform database upgrades and downgrades.
version: 1,
);

Insérer une Personne dans la base de données :

Maintenant que vous disposez d'une base de données avec une table permettant de stocker des
informations sur différents personnes, il est temps de lire et d'écrire des données.

Tout d'abord, insérez un chien dans la table personnes . Cette opération comporte deux étapes :

Convertir le personne en une map.

Utiliser la méthode insert() pour stocker la carte dans la table personnes .

class Personne {
final int id;
final String name;
final int age;

Personne({
required [Link],
required [Link],
required [Link],
});

// Convert a Personne into a Map. The keys must correspond to the names of the
// columns in the database.
Map<String, Object?> toMap() {
return {
'id': id,
'name': name,
'age': age,
};
}

// Implement toString to make it easier to see information about


// each dog when using the print statement.
@override
String toString() {
return 'Personne{id: $id, name: $name, age: $age}';
}
}

// Define a function that inserts Personnes into the database


Future<void> insertPersonne(Personne personne) async {
// Get a reference to the database.
final db = await database;

// Insert the Personne into the correct table. You might also specify the
// `conflictAlgorithm` to use in case the same Personnes is inserted twice.
//
// In this case, replace any previous data.
await [Link](
'personnes',
[Link](),
conflictAlgorithm: [Link],
);
}

// Create a Personne and add it to the personnes table


var per = Personne(
id: 0,
name: 'Yassine',
age: 35,
);

await insertPersonne(per);

Récupérer la liste des personnes

Maintenant qu'une personne est stockée dans la base de données, interrogez la base de données pour
obtenir une personne spécifique ou une liste de toutes les personnes. Cette opération s'effectue en
deux étapes :

• Exécutez une requête sur la table personnes. This returns a List<Map>.


• Convertir la List<Map> en List<Personne>.

// A method that retrieves all the personnes from the personnes table.
Future<List<Personne>> personnes() async {
// Get a reference to the database.
final db = await database;

// Query the table for all the personnes.


final List<Map<String, Object?>> personneMaps = await [Link]('personnes');

// Convert the list of each personne’s fields into a list of `Personnes` objects.
return [
for (final {
'id': id as int,
'name': name as String,
'age': age as int,
} in personneMaps)
Personne(id: id, name: name, age: age),
];
}

print(await personnes()); // Prints a list .

Mise à jour d'une personne dans la base de données :


Après avoir inséré des informations dans la base de données, il se peut que vous souhaitiez les
mettre à jour ultérieurement. Pour ce faire, vous pouvez utiliser la méthode update() de la
bibliothèque sqflite.

Cette méthode comporte deux étapes :

• Convertir la personne en carte.


• Utilisez une clause where pour vous assurer que vous mettez à jour la bonne personne.

Future<void> updatePersonne(Personne personne) async {


// Get a reference to the database.
final db = await database;

// Update the given Personne.


await [Link](
'personnes',
[Link](),
// Ensure that the Personne has a matching id.
where: 'id = ?',
// Pass the Personne's id as a where Arg to prevent SQL injection.
whereArgs: [[Link]],
);
}

// Update and save it to the database.


pr = Personne(
id: [Link],
name: [Link],
age: [Link] + 7,
);
await updatePersonne(pr);

// Print the updated results.


print(await personnes()); //

Supprimer un chien de la base de données :

Outre l'insertion et la mise à jour d'informations sur les chiens, vous pouvez également supprimer
des personnes de la base de données. Pour supprimer des données, utilisez la méthode delete() de la
bibliothèque sqflite.

Dans cette section, créez une fonction qui prend un identifiant et supprime de la base de données le
chien dont l'identifiant correspond. Pour que cela fonctionne, vous devez fournir une clause where
afin de limiter les enregistrements à supprimer.

Future<void> deletePersonne(int id) async {


// Get a reference to the database.
final db = await database;

// Remove the Personne from the database.


await [Link](
'personnes',
// Use a `where` clause to delete a specific dog.
where: 'id = ?',
// Pass the Personne's id as a whereArg to prevent SQL injection.
whereArgs: [id],
);
}

10. Rest API et Flutter


Flutter fournit un package http pour utiliser les ressources http. Le package http utilise les
fonctionnalités d'attente et asynchrone et fournit de nombreuses méthodes de haut niveau telles que
les méthodes de lecture, d'obtention, de publication, de mise, de tête et de suppression pour l'envoi
et la réception de données à partir d'emplacements distants. Ces méthodes simplifient le
développement d'applications mobiles basées sur REST.

Le package http fournit également une classe de client http standard qui prend en charge la
connexion persistante. Cette classe est utile lorsque de nombreuses requêtes doivent être effectuées
sur un serveur particulier. Il doit être fermé correctement en utilisant la méthode close (). Sinon,
cela fonctionne comme une classe http. Le code suivant l'explique plus clairement.

var client = new [Link]();

try {
print(await [Link]('[Link]
}
finally {
[Link]();
}

Installez le dernier package http et ajoutez-le au projet.

Pour installer le package http, ouvrez le fichier [Link] dans le dossier de votre projet et
ajoutez le package http dans la section des dépendances.
[Link]

dependencies:

http: <latest_version>

Vous pouvez importer le package http sous la forme:

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

La méthode Get :
Future<[Link]> fetchPost() {

return [Link]('[Link]
}

La méthode Post :
class Post {

final int userId;


final int id;
final String title;
final String body;

Post({[Link], [Link], [Link], this. description});

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


return Post(
userId: json['userId'],
id: json['id'],
title: json['title'],
description: json['description'],
);
}
}

Future<Post> fetchPost() async {

final response = await [Link]( Give the link of JSON file');

if ([Link] == 200) {
// If the server returns an OK response, then parse the JSON.
return [Link]([Link]([Link]));
} else {
// If the response was umexpected, throw an error.
throw Exception('Failed to load post');
}
}

Exemple Complet :

import 'dart:async';

import 'dart:convert';

import 'package:flutter/[Link]';
import 'package:http/[Link]' as http;
void main() => runApp(MyApp());

class MyApp extends StatefulWidget {


MyApp({Key key}) : super(key: key);

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

class _MyAppState extends State<MyApp> {


Future<Post> post;

@override
void initState() {
[Link]();
post = fetchPost();
}

@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter REST API Example',
theme: ThemeData(
primarySwatch: [Link],
),
home: Scaffold(
appBar: AppBar(
title: Text('Flutter REST API Example'),
),
body: Center(
child: FutureBuilder<Post>(
future: post,
builder: (context, abc) {
if ([Link]) {
return Text([Link]);
} else if ([Link]) {
return Text("${[Link]}");
}

// By default, it show a loading spinner.


return CircularProgressIndicator();
},
),
),
),
);
}
}

Future<Post> fetchPost() async {


final response = await [Link]('Give your JSON file web link.');

if ([Link] == 200) {
// If the call to the server was successful (returns OK), parse the JSON.
return [Link]([Link]([Link]));
} else {
// If that call was not successful (response was unexpected), it throw an error.
throw Exception('Failed to load post');
}
}

class Post {
final int userId;
final int id;
final String title;
final String description;

Post({[Link], [Link], [Link], this. description});

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


return Post(
userId: json['userId'],
id: json['id'],
title: json['title'],
description: json[' description'],
);
}
}

References :
[Link]
[Link]

Vous aimerez peut-être aussi