Flutter Templates
Créer une application de chat en temps réel dans Flutter avec Back4App
36 min
introduction créer une application de chat implique de gérer des données en temps réel, l'authentification des utilisateurs, la gestion des médias et un stockage de données efficace dans ce tutoriel, vous apprendrez à construire une application de chat en temps réel dans flutter qui prend en charge les conversations individuelles et de groupe, les statuts des messages et le partage de médias nous utiliserons back4app—un backend en tant que service alimenté par parse server—pour gérer les fonctionnalités backend à la fin de ce tutoriel, vous aurez une application de chat entièrement fonctionnelle avec les fonctionnalités suivantes authentification des utilisateurs processus d'inscription et de connexion sécurisés messagerie en temps réel livraison instantanée des messages utilisant des requêtes en direct présence des utilisateurs suivi du statut en ligne/hors ligne des utilisateurs stockage de médias envoi et réception d'images dans les chats historique des messages conservation des historiques de chat pour les utilisateurs prérequis pour suivre ce tutoriel, vous aurez besoin de flutter sdk installé sur votre machine suivez le guide d'installation officiel de flutter https //flutter dev/docs/get started/install connaissances de base en flutter et dart un ide ou éditeur de texte tel que visual studio code ou android studio un compte back4app inscrivez vous pour un compte gratuit sur back4app https //www back4app com/ parse server sdk pour flutter ajouté à votre projet aperçu nous allons construire une application de chat avec les composants suivants authentification des utilisateurs les utilisateurs peuvent s'inscrire et se connecter liste de contacts afficher une liste d'utilisateurs avec qui discuter écran de chat interface de messagerie en temps réel partage de médias capacité d'envoyer et de recevoir des images statut en ligne afficher le statut en ligne/hors ligne des utilisateurs étape 1 – configuration du projet flutter 1 1 créer un nouveau projet flutter ouvrez votre terminal et exécutez flutter create chat app naviguez vers le répertoire du projet cd chat app 1 2 ajouter des dépendances ouvrez pubspec yaml et ajoutez les dépendances suivantes dependencies flutter sdk flutter parse server sdk flutter ^4 0 1 image picker ^0 8 4+3 cached network image ^3 2 0 uuid ^3 0 4 exécutez flutter pub get pour installer les paquets parse server sdk flutter interagir avec back4app image picker choisir des images depuis la galerie ou l'appareil photo cached network image chargement et mise en cache efficaces des images uuid générer des identifiants uniques étape 2 – configuration de back4app 2 1 créer une nouvelle application back4app connectez vous à votre tableau de bord back4app https //dashboard back4app com/ cliquez sur "créer une nouvelle application" entrez un nom pour votre application, par exemple, "chatapp" , et cliquez sur "créer" 2 2 configurer les classes et le modèle de données nous allons créer les classes suivantes utilisateur (classe parse par défaut) stocke les informations des utilisateurs message stocke les messages de chat chatroom représente un chat entre utilisateurs 2 2 1 classe utilisateur champs nom d'utilisateur chaîne mot de passe chaîne email chaîne estenligne booléen avatar fichier (optionnel) le user classe est intégrée ; nous devons juste nous assurer qu'elle a les champs supplémentaires 2 2 2 classe message champs expéditeur pointeur< user> destinataire pointeur< user> chatroomid chaîne contenu chaîne image fichier (optionnel) crééà datetime (ajouté automatiquement) 2 2 3 classe chatroom champs chatroomid chaîne utilisateurs tableau de pointeur< user> derniermessage chaîne misàjour datetime (mis à jour automatiquement) 2 3 obtenir les identifiants de l'application naviguez vers paramètres de l'application > sécurité et clés notez votre id d'application et clé client étape 3 – initialiser parse dans votre application flutter ouvrez lib/main dart et modifiez le comme suit import 'package\ flutter/material dart'; import 'package\ parse server sdk flutter/parse server sdk dart'; import 'screens/login screen dart'; // you'll create this file next void main() async { widgetsflutterbinding ensureinitialized(); const keyapplicationid = 'your application id'; const keyclientkey = 'your client key'; const keyparseserverurl = 'https //parseapi back4app com'; await parse() initialize( keyapplicationid, keyparseserverurl, clientkey keyclientkey, autosendsessionid true, debug true, ); runapp(myapp()); } class myapp extends statelesswidget { @override widget build(buildcontext context) { return materialapp( title 'chat app', theme themedata( primaryswatch colors blue, ), home loginscreen(), ); } } remplacez 'your application id' et 'your client key' par vos véritables identifiants back4app étape 4 – mise en œuvre de l'authentification des utilisateurs 4 1 créer un service d'authentification créez un nouveau répertoire appelé services sous lib et ajoutez un fichier nommé auth service dart // lib/services/auth service dart import 'package\ parse server sdk flutter/parse server sdk dart'; class authservice { future\<parseuser?> signup(string username, string email, string password) async { var user = parseuser(username, password, email); var response = await user signup(); if (response success) { return user; } else { return null; } } future\<parseuser?> login(string username, string password) async { var user = parseuser(username, password, null); var response = await user login(); if (response success) { return user; } else { return null; } } future\<void> logout() async { var user = await parseuser currentuser() as parseuser?; await user? logout(); } future\<parseuser?> getcurrentuser() async { return await parseuser currentuser() as parseuser?; } } 4 2 créer des écrans de connexion et d'inscription créez un nouveau répertoire appelé screens sous lib et ajoutez des fichiers nommés login screen dart et signup screen dart 4 2 1 écran de connexion // lib/screens/login screen dart import 'package\ flutter/material dart'; import ' /services/auth service dart'; import 'home screen dart'; import 'signup screen dart'; class loginscreen extends statelesswidget { final authservice authservice = authservice(); final texteditingcontroller usernamecontroller = texteditingcontroller(); final texteditingcontroller passwordcontroller = texteditingcontroller(); void login(buildcontext context) async { var user = await authservice login( usernamecontroller text trim(), passwordcontroller text trim(), ); if (user != null) { navigator pushreplacement( context, materialpageroute(builder (context) => homescreen()), ); } else { scaffoldmessenger of(context) showsnackbar(snackbar(content text('login failed'))); } } @override widget build(buildcontext context) { return scaffold( appbar appbar( title text('chat app login'), ), body padding( padding const edgeinsets all(16), child column( children \[ textfield( controller usernamecontroller, decoration inputdecoration(labeltext 'username'), ), textfield( controller passwordcontroller, decoration inputdecoration(labeltext 'password'), obscuretext true, ), sizedbox(height 20), elevatedbutton( onpressed () => login(context), child text('login'), ), textbutton( onpressed () => navigator push( context, materialpageroute(builder (context) => signupscreen())), child text('don\\'t have an account? sign up'), ), ], ), ), ); } } 4 2 2 écran d’inscription // lib/screens/signup screen dart import 'package\ flutter/material dart'; import ' /services/auth service dart'; import 'home screen dart'; class signupscreen extends statelesswidget { final authservice authservice = authservice(); final texteditingcontroller usernamecontroller = texteditingcontroller(); final texteditingcontroller emailcontroller = texteditingcontroller(); final texteditingcontroller passwordcontroller = texteditingcontroller(); void signup(buildcontext context) async { var user = await authservice signup( usernamecontroller text trim(), emailcontroller text trim(), passwordcontroller text trim(), ); if (user != null) { navigator pushreplacement( context, materialpageroute(builder (context) => homescreen()), ); } else { scaffoldmessenger of(context) showsnackbar(snackbar(content text('sign up failed'))); } } @override widget build(buildcontext context) { return scaffold( appbar appbar( title text('chat app sign up'), ), body padding( padding const edgeinsets all(16), child column( children \[ textfield( controller usernamecontroller, decoration inputdecoration(labeltext 'username'), ), textfield( controller emailcontroller, decoration inputdecoration(labeltext 'email'), ), textfield( controller passwordcontroller, decoration inputdecoration(labeltext 'password'), obscuretext true, ), sizedbox(height 20), elevatedbutton( onpressed () => signup(context), child text('sign up'), ), ], ), ), ); } } étape 5 – mise en œuvre de la présence de l'utilisateur 5 1 mettre à jour le statut en ligne de l'utilisateur créer une méthode dans authservice pour mettre à jour le statut en ligne de l'utilisateur // lib/services/auth service dart class authservice { // existing methods future\<void> updateuseronlinestatus(bool isonline) async { var user = await parseuser currentuser() as parseuser?; if (user != null) { user set('isonline', isonline); await user save(); } } } 5 2 définir le statut en ligne lors de la connexion et de la déconnexion mettre à jour les méthodes de connexion et de déconnexion // lib/services/auth service dart class authservice { // existing methods future\<parseuser?> login(string username, string password) async { var user = parseuser(username, password, null); var response = await user login(); if (response success) { await updateuseronlinestatus(true); return user; } else { return null; } } future\<void> logout() async { await updateuseronlinestatus(false); var user = await parseuser currentuser() as parseuser?; await user? logout(); } } étape 6 – affichage de la liste des contacts 6 1 créer le service utilisateur créer user service dart sous services // lib/services/user service dart import 'package\ parse server sdk flutter/parse server sdk dart'; class userservice { future\<list\<parseuser>> getallusers() async { final querybuilder\<parseuser> queryusers = querybuilder\<parseuser>(parseuser forquery()); final parseresponse apiresponse = await queryusers query(); if (apiresponse success && apiresponse results != null) { return apiresponse results as list\<parseuser>; } else { return \[]; } } } 6 2 créer l'écran d'accueil // lib/screens/home screen dart import 'package\ flutter/material dart'; import 'package\ parse server sdk flutter/parse server sdk dart'; import ' /services/user service dart'; import ' /services/auth service dart'; import 'chat screen dart'; class homescreen extends statefulwidget { @override homescreenstate createstate() => homescreenstate(); } class homescreenstate extends state\<homescreen> { final userservice userservice = userservice(); final authservice authservice = authservice(); list\<parseuser> users = \[]; parseuser? currentuser; @override void initstate() { super initstate(); fetchusers(); getcurrentuser(); } void getcurrentuser() async { currentuser = await authservice getcurrentuser(); } void fetchusers() async { var allusers = await userservice getallusers(); setstate(() { users = allusers where((user) => user username != currentuser? username) tolist(); }); } void logout(buildcontext context) async { await authservice logout(); navigator pushreplacementnamed(context, '/'); } @override widget build(buildcontext context) { return scaffold( appbar appbar( title text('contacts'), actions \[ iconbutton(onpressed () => logout(context), icon icon(icons logout)), ], ), body listview\ builder( itemcount users length, itembuilder (context, index) { var user = users\[index]; return listtile( title text(user username ?? ''), subtitle text(user get('isonline') == true ? 'online' 'offline'), ontap () { navigator push( context, materialpageroute(builder (context) => chatscreen(receiver user)), ); }, ); }, ), ); } } étape 7 – mise en œuvre de la messagerie en temps réel avec des requêtes en direct 7 1 configurer le client de requête en direct ajoutez la dépendance suivante dans pubspec yaml dependencies flutter sdk flutter parse server sdk flutter git url https //github com/parse community/parse sdk flutter git ref master cela garantit que vous avez la dernière version avec le support de live query 7 2 initialiser live query dans main dart // lib/main dart void main() async { widgetsflutterbinding ensureinitialized(); const keyapplicationid = 'your application id'; const keyclientkey = 'your client key'; const keyparseserverurl = 'https //parseapi back4app com'; const livequeryurl = 'wss\ //your app back4app io'; await parse() initialize( keyapplicationid, keyparseserverurl, clientkey keyclientkey, autosendsessionid true, debug true, livequeryurl livequeryurl, ); runapp(myapp()); } remplacez 'your app' par le sous domaine de votre application back4app 7 3 créer l'écran de chat // lib/screens/chat screen dart import 'package\ flutter/material dart'; import 'package\ parse server sdk flutter/parse server sdk dart'; import 'package\ uuid/uuid dart'; import 'package\ image picker/image picker dart'; import ' /services/auth service dart'; import 'package\ cached network image/cached network image dart'; class chatscreen extends statefulwidget { final parseuser receiver; chatscreen({required this receiver}); @override chatscreenstate createstate() => chatscreenstate(); } class chatscreenstate extends state\<chatscreen> { final authservice authservice = authservice(); parseuser? currentuser; list\<parseobject> messages = \[]; string chatroomid = ''; final texteditingcontroller messagecontroller = texteditingcontroller(); late parselivelist\<parseobject> livemessages; @override void initstate() { super initstate(); getcurrentuser(); setupchatroom(); } void getcurrentuser() async { currentuser = await authservice getcurrentuser(); if (currentuser != null) { setuplivequery(); } } void setupchatroom() { string userid = currentuser! objectid!; string receiverid = widget receiver objectid!; chatroomid = userid compareto(receiverid) > 0 ? '$userid $receiverid' '$receiverid $userid'; } void setuplivequery() { querybuilder\<parseobject> querymessages = querybuilder\<parseobject>(parseobject('message')) whereequalto('chatroomid', chatroomid) orderbyascending('createdat'); livemessages = parselivelist\<parseobject>( querymessages, listeningincludes \['sender'], lazyloading false, ); setstate(() {}); } void sendmessage({string? content, parsefilebase? imagefile}) async { var message = parseobject('message') set('sender', currentuser) set('receiver', widget receiver) set('chatroomid', chatroomid) set('content', content ?? '') set('image', imagefile); await message save(); messagecontroller clear(); } void pickimage() async { final picker = imagepicker(); final pickedfile = await picker pickimage(source imagesource gallery, imagequality 50); if (pickedfile != null) { var file = parsefile(file(pickedfile path)); await file save(); sendmessage(imagefile file); } } @override void dispose() { livemessages dispose(); super dispose(); } @override widget build(buildcontext context) { if (currentuser == null || livemessages == null) { return scaffold( appbar appbar( title text('chat with ${widget receiver username}'), ), body center(child circularprogressindicator()), ); } return scaffold( appbar appbar( title text('chat with ${widget receiver username}'), ), body column( children \[ expanded( child parselivelistwidget\<parseobject>( query livemessages, reverse false, lazyloading false, childbuilder (context, snapshot) { if (snapshot failed) { return text('error ${snapshot error}'); } else if (snapshot hasdata) { var message = snapshot loadeddata!; var sender = message get\<parseuser>('sender')!; var isme = sender objectid == currentuser! objectid; var content = message get\<string>('content') ?? ''; var image = message get\<parsefilebase>('image'); return align( alignment isme ? alignment centerright alignment centerleft, child container( padding edgeinsets all(8), margin edgeinsets all(8), decoration boxdecoration( color isme ? colors blue\[100] colors grey\[300], borderradius borderradius circular(8), ), child column( crossaxisalignment crossaxisalignment start, children \[ if (content isnotempty) text(content), if (image != null) cachednetworkimage( imageurl image url!, placeholder (context, url) => circularprogressindicator(), errorwidget (context, url, error) => icon(icons error), ), ], ), ), ); } else { return container(); } }, ), ), divider(height 1), container( padding edgeinsets symmetric(horizontal 8), color colors white, child row( children \[ iconbutton( icon icon(icons photo), onpressed pickimage, ), expanded( child textfield( controller messagecontroller, decoration inputdecoration collapsed(hinttext 'type a message'), ), ), iconbutton( icon icon(icons send), onpressed () { if ( messagecontroller text trim() isnotempty) { sendmessage(content messagecontroller text trim()); } }, ), ], ), ), ], ), ); } } explication parselivelistwidget un widget qui écoute les mises à jour de requêtes en direct et se reconstruit lorsque les données changent sendmessage() envoie un message texte ou une image pickimage() utilise image picker pour sélectionner une image et l'envoie comme message setuplivequery() configure une requête en direct pour écouter les nouveaux messages dans la salle de chat étape 8 – tester l'application 8 1 exécuter l'application dans votre terminal, exécutez flutter run 8 2 test de messagerie ouvrez l'application sur deux appareils ou émulateurs inscrivez vous ou connectez vous avec des comptes utilisateurs différents à partir d'un compte, sélectionnez l'autre utilisateur dans la liste de contacts envoyez des messages et des images ; ils devraient apparaître en temps réel sur les deux appareils conclusion félicitations ! vous avez construit une application de chat en temps réel en flutter en utilisant back4app cette application prend en charge authentification des utilisateurs connexion et inscription sécurisées messagerie en temps réel mises à jour instantanées utilisant des requêtes en direct présence des utilisateurs suivi du statut en ligne/hors ligne partage de médias envoi et réception d'images historique des messages persistance des messages de chat prochaines étapes discussions de groupe étendre l'application pour prendre en charge les conversations de groupe statuts des messages implémenter des accusés de lecture et des indicateurs de saisie notifications push envoyer des notifications pour les nouveaux messages lorsque l'application est en arrière plan photos de profil permettre aux utilisateurs de télécharger des avatars améliorations de la sécurité sécuriser les données avec des acl et des autorisations basées sur les rôles ressources supplémentaires documentation back4app https //www back4app com/docs guide du sdk parse pour flutter https //docs parseplatform org/flutter/guide/ documentation officielle de flutter https //flutter dev/docs requête en direct parse https //docs parseplatform org/js/guide/#live queries bon codage !