Flutter Templates
Crea un'applicazione di chat in tempo reale in Flutter con Back4App.
36 min
introduzione creare un'applicazione di chat implica la gestione di dati in tempo reale, autenticazione degli utenti, gestione dei media e archiviazione efficiente dei dati in questo tutorial, imparerai a costruire un'applicazione di chat in tempo reale in flutter che supporta conversazioni uno a uno e di gruppo, stati dei messaggi e condivisione di media utilizzeremo back4app—un backend as a service alimentato da parse server—per gestire le funzionalità di backend alla fine di questo tutorial, avrai un'app di chat completamente funzionale con le seguenti caratteristiche autenticazione utente processi di registrazione e accesso sicuri messaggistica in tempo reale consegna istantanea dei messaggi utilizzando live queries presenza utente monitoraggio dello stato online/offline degli utenti archiviazione media invio e ricezione di immagini nelle chat cronologia messaggi persistenza delle cronologie chat per gli utenti prerequisiti per seguire questo tutorial, avrai bisogno di flutter sdk installato sul tuo computer segui la guida ufficiale all'installazione di flutter https //flutter dev/docs/get started/install conoscenze di base di flutter e dart un ide o editor di testo come visual studio code o android studio un account back4app registrati per un account gratuito su back4app https //www back4app com/ parse server sdk per flutter aggiunto al tuo progetto panoramica costruiremo un'applicazione di chat con i seguenti componenti autenticazione utente gli utenti possono registrarsi e accedere elenco contatti visualizza un elenco di utenti con cui chattare schermata chat interfaccia di messaggistica in tempo reale condivisione media possibilità di inviare e ricevere immagini stato online visualizza lo stato online/offline degli utenti passo 1 – configurazione del progetto flutter 1 1 crea un nuovo progetto flutter apri il tuo terminale e esegui flutter create chat app naviga nella directory del progetto cd chat app 1 2 aggiungi dipendenze apri pubspec yaml e aggiungi le seguenti dipendenze 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 esegui flutter pub get per installare i pacchetti parse server sdk flutter interagisci con back4app image picker seleziona immagini dalla galleria o dalla fotocamera cached network image caricamento e caching delle immagini efficienti uuid genera identificatori unici passo 2 – configurazione di back4app 2 1 crea una nuova applicazione back4app accedi al tuo dashboard di back4app https //dashboard back4app com/ clicca su "crea nuova app" inserisci un nome per la tua applicazione, ad esempio, "chatapp" , e clicca su "crea" 2 2 configura classi e modello di dati creeremo le seguenti classi utente (classe parse predefinita) memorizza le informazioni sugli utenti messaggio memorizza i messaggi della chat chatroom rappresenta una chat tra utenti 2 2 1 classe utente campi nome utente string password string email string èonline boolean avatar file (opzionale) il user classe è integrata; dobbiamo solo assicurarci che abbia i campi aggiuntivi 2 2 2 classe messaggio campi mittente pointer< user> ricevente pointer< user> chatroomid string contenuto string immagine file (opzionale) creatoil datetime (aggiunto automaticamente) 2 2 3 classe chatroom campi chatroomid string utenti array of pointer< user> lastmessage string updatedat datetime (aggiornato automaticamente) 2 3 ottenere le credenziali dell'applicazione naviga a impostazioni app > sicurezza e chiavi annota il tuo id applicazione e chiave client passo 3 – inizializzare parse nella tua app flutter apri lib/main dart e modificalo come segue 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(), ); } } sostituisci 'your application id' e 'your client key' con le tue credenziali effettive di back4app passo 4 – implementazione dell'autenticazione utente 4 1 crea il servizio di autenticazione crea una nuova directory chiamata services sotto lib e aggiungi un file chiamato 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 crea schermate di accesso e registrazione crea una nuova directory chiamata screens sotto lib e aggiungi file chiamati login screen dart e signup screen dart 4 2 1 schermata di accesso // 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 schermata di registrazione // 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'), ), ], ), ), ); } } passo 5 – implementazione della presenza utente 5 1 aggiorna lo stato online dell'utente crea un metodo in authservice per aggiornare lo stato online dell'utente // 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 imposta lo stato online al login e logout aggiorna i metodi di login e logout // 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(); } } passo 6 – visualizzazione della lista dei contatti 6 1 crea il servizio utente crea user service dart sotto 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 crea la schermata principale // 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)), ); }, ); }, ), ); } } passaggio 7 – implementazione della messaggistica in tempo reale con query live 7 1 configurare il client di query live aggiungi la seguente dipendenza in pubspec yaml dependencies flutter sdk flutter parse server sdk flutter git url https //github com/parse community/parse sdk flutter git ref master questo garantisce che tu abbia l'ultima versione con supporto per live query 7 2 inizializza live query in 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()); } sostituisci 'your app' con il tuo sottodominio dell'applicazione back4app 7 3 crea schermata 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()); } }, ), ], ), ), ], ), ); } } spiegazione parselivelistwidget un widget che ascolta gli aggiornamenti delle query in tempo reale e si ricostruisce quando i dati cambiano sendmessage() invia un messaggio di testo o un'immagine pickimage() usa image picker per selezionare un'immagine e inviarla come messaggio setuplivequery() configura una query in tempo reale per ascoltare nuovi messaggi nella chat passo 8 – testare l'app 8 1 esegui l'app nel tuo terminale, esegui flutter run 8 2 test messaging apri l'app su due dispositivi o emulatori registrati o accedi con account utente diversi da un account, seleziona l'altro utente dalla lista dei contatti invia messaggi e immagini; dovrebbero apparire in tempo reale su entrambi i dispositivi conclusione congratulazioni! hai costruito un'applicazione di chat in tempo reale in flutter utilizzando back4app questa app supporta autenticazione utente accesso e registrazione sicuri messaggistica in tempo reale aggiornamenti istantanei utilizzando live queries presenza utente monitoraggio dello stato online/offline condivisione media invio e ricezione di immagini cronologia messaggi persistenza dei messaggi di chat prossimi passi chat di gruppo estendere l'app per supportare conversazioni di gruppo stati dei messaggi implementare ricevute di lettura e indicatori di digitazione notifiche push inviare notifiche per nuovi messaggi quando l'app è in background immagini del profilo consentire agli utenti di caricare avatar miglioramenti della sicurezza proteggere i dati con acl e permessi basati sui ruoli risorse aggiuntive documentazione di back4app https //www back4app com/docs guida al parse sdk per flutter https //docs parseplatform org/flutter/guide/ documentazione ufficiale di flutter https //flutter dev/docs query live di parse https //docs parseplatform org/js/guide/#live queries buona programmazione!