Slide 1

Slide 1 text

Let’s build a Flutter app (fast!) Ian Oliveira Mobile Software Enginner Community Manager 18/04/2024

Slide 2

Slide 2 text

Agenda What is Flutter? What is Firebase? Set up Firebase and Flutter projects Add Firebase Auth Add Firestore query Display Firestore data Write to Firestore 01. 02. 03. 04. 05. 06. 07.

Slide 3

Slide 3 text

3 Quem sou eu? 1. Parnaíba no Litoral do Piauí 1. Bacharel em Ciência da Computação pela UESPI - Parnaíba 2. Cursando especialização em Mobile pelo IFPI 3. Desenvolvedor Flutter Especialista na EXA 4. Fundador e organizador do GDG Parnaíba & Flutter Piauí 5. +12.5k de leituras no blog do Medium 6. (Travel lover) Amante de viagens ✈

Slide 4

Slide 4 text

Flutter Google’s portable UI toolkit for building beautiful multi-platform applications

Slide 5

Slide 5 text

Portable Write once, run anywhere iOS Android Web Windows Mac OS Linux Embedded

Slide 6

Slide 6 text

Firebase Remote Config A/B Testing Personalization Authentication Firestore Cloud Storage Hosting Realtime Database App Check Cloud Functions Extensions Machine Learning Crashlytics Test Lab Performance Monitoring App Distribution Analytics Cloud Messaging In-App Messaging Build your backend Improve app quality Engage users effectively

Slide 7

Slide 7 text

Architecture

Slide 8

Slide 8 text

Set up Firebase and Flutter projects 02

Slide 9

Slide 9 text

$ flutter create chatapp --empty $ cd chatapp $ flutterfire configure Initialize project on the command line

Slide 10

Slide 10 text

dependencies: flutter: sdk: flutter firebase_core: ^2.30.0 cloud_firestore: ^4.19.2 firebase_auth: ^4.17.0 pubspec.yaml

Slide 11

Slide 11 text

void main() async { WidgetsFlutterBinding.ensureInitialized(); await Firebase.initializeApp( options: DefaultFirebaseOptions.currentPlatform ); runApp(const MyApp()); } Add project structure

Slide 12

Slide 12 text

static const FirebaseOptions web = FirebaseOptions( apiKey: 'AIzaSyCsdkfu d9 dfkj9 qiuODNUXmGnTdGk', appId: '1:12341234:-AppID:129038120983--', messagingSenderId: '1234', projectId: 'chat-app', authDomain: 'chat-app.firebaseapp.com', storageBucket: 'chat-app.appspot.com', ); firebase_options.dart

Slide 13

Slide 13 text

class MyApp extends StatelessWidget { Widget build(BuildContext context) { return MaterialApp( title: 'Chat App', home: const ChatPage(), ); } } Add project structure

Slide 14

Slide 14 text

Add Firebase Auth 03

Slide 15

Slide 15 text

class ChatPage extends StatelessWidget { // ... Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text("Meetup Chat App"), centerTitle: false, actions: [ // TODO: add login Button ], ), body: ChatView(), ); } } Add ChatPage widget

Slide 16

Slide 16 text

actions: [ ElevatedButton( onPressed: () async { final auth = FirebaseAuth.instance; if (auth.currentUser != null) { await auth.signOut(); } else { await auth.signInAnonymously(); } }, child: Text('Log In Or Out'), ), ], Add authentication to ChatPage widget

Slide 17

Slide 17 text

class ChatView extends StatelessWidget { const ChatView({super.key}); @override Widget build(BuildContext context) { return StreamBuilder( stream: FirebaseAuth.instance.authStateChanges(), builder: (context, authSnapshot) { // TODO: Add UI }, ); } } Add ChatView widget

Slide 18

Slide 18 text

class ChatView extends StatelessWidget { const ChatView({super.key}); @override Widget build(BuildContext context) { return StreamBuilder( stream: FirebaseAuth.instance.authStateChanges(), builder: (context, authSnapshot) { // TODO: Add UI }, ); } } Add ChatView widget

Slide 19

Slide 19 text

Widget build(BuildContext context) { return StreamBuilder( stream: FirebaseAuth.instance.authStateChanges(), builder: (context, snapshot) { return Column( children: [ Text('User id: ${authSnapshot.data?.uid}'), // rest of app ], ); }, ); } Add ChatView widget

Slide 20

Slide 20 text

Query Firestore 04

Slide 21

Slide 21 text

Create the Message class class Message { final String uid; final String message; final Timestamp? timestamp; Message({ required this.uid, required this.message, this.timestamp, }); }

Slide 22

Slide 22 text

class Message { // ... factory Message.fromFirestore(DocumentSnapshot data) { return Message( uid: data['uid'], message: data['message'], timestamp: data['timestamp'], ); } } Create the Message class

Slide 23

Slide 23 text

Create a class for Firestore data class Message { //... Map toFirestore() { return { 'uid': uid, 'message': message, 'timestamp': timestamp ?? Timestamp.now(), }; } }

Slide 24

Slide 24 text

Messages Firestore query final messagesQuery = FirebaseFirestore.instance.collection('messages') .orderBy('timestamp', descending: true);

Slide 25

Slide 25 text

Display Firestore data 05

Slide 26

Slide 26 text

class ChatView extends StatelessWidget { const ChatView({super.key}); @override Widget build(BuildContext context) { return StreamBuilder( stream: FirebaseAuth.instance.authStateChanges(), builder: (context, snapshot) { return Column( children: [ Text('User: ${snapshot.data?.uid}'), // rest of app ], ); // ... ChatView widget

Slide 27

Slide 27 text

Read Firestore Data return Column( children: [ // ... Expanded( child: StreamBuilder( stream: messagesQuery.snapshots(), builder: (context, messagesSnapshot) { // TODO: add ui }, ), ), // ...

Slide 28

Slide 28 text

Read Firestore data StreamBuilder( stream: messagesQuery.snapshots(), builder: (context, messagesSnapshot) { if (messagesSnapshot.connectionState == ConnectionState.waiting){ return const Center(child: CircularProgressIndicator()); }

Slide 29

Slide 29 text

Read Firestore data StreamBuilder( stream: messagesQuery.snapshots(), builder: (context, messagesSnapshot) { // ... if(authsnapshot.hasData) return ListView.builder( reverse: true, itemCount: messagesSnapshot.data!.size, itemBuilder: (BuildContext context, int idx) { final message = Message.fromFirestore(messagesSnapshots.data!.docs[idx]); return ChatBubble(text: message.message); } ); } );

Slide 30

Slide 30 text

Write to Firestore 06

Slide 31

Slide 31 text

Read Firestore data return Column( children: [ //... if(authsnapshot.hasData) ChatTextInput( onSend: (message) { FirebaseFirestore.instance .collection('messages').add( Message( uid: authSnapshot.data!.uid, message: message, ).toFirestore(), ); }, ), ],

Slide 32

Slide 32 text

Deploy 06

Slide 33

Slide 33 text

Firebase Hosting $ firebase experiments:enable webframeworks $ firebase init hosting

Slide 34

Slide 34 text

{ "hosting": { "source": "." } } firebase.json

Slide 35

Slide 35 text

firebase deploy Deploy

Slide 36

Slide 36 text

Demo via Firebase Hosting https://talkmeetup.web.app/ Demo

Slide 37

Slide 37 text

Thank you! Learn more about Flutter and Firebase! Ian Oliveira Mobile Software Enginner Community Manager @ianoliveira.dev Ian oliveira @ianoliveirag12