Flutter & Firebase Tutorial – Realtime Database

flutter-realtime-db-example
flutter-realtime-db-example

Let’s explore firebase realtime database by creating a simple chat app. where anyone can post message publically

Step 1: Configure Firebase & Flutter

Before starting this, You must complete: Firebase Flutter Setup

Step 2: Adding Dependencies

Once you have completed setup. now we can add required packages with your pubspec.yaml. In our case, we need to add realtime database (firebase_database), intl (for timestamp handling)

<span class="hljs-selector-tag">dependencies</span>:
  <span class="hljs-selector-tag">flutter</span>:
    <span class="hljs-selector-tag">sdk</span>: <span class="hljs-selector-tag">flutter</span>
  <span class="hljs-selector-tag">cupertino_icons</span>: ^0<span class="hljs-selector-class">.1</span><span class="hljs-selector-class">.2</span>
  <span class="hljs-selector-tag">firebase_core</span>: ^0<span class="hljs-selector-class">.4</span><span class="hljs-selector-class">.0</span>+6
  <span class="hljs-selector-tag">firebase_database</span>: ^3<span class="hljs-selector-class">.0</span><span class="hljs-selector-class">.4</span>
  <span class="hljs-selector-tag">intl</span>: ^0<span class="hljs-selector-class">.15</span><span class="hljs-selector-class">.8</span>

Step 3: Working with Code

Now we can start writing code with our main.dart

Let’s create a db reference chat to store our messages. & _txtCtrl for handling user inputs

<span class="hljs-attribute">var</span> _firebaseRef = FirebaseDatabase().reference().child(<span class="hljs-string">'chats'</span>);
<span class="hljs-attribute">TextEditingController</span> _txtCtrl = TextEditingController();

Now using _firebaseRef we can add, read, update, delete data with chat

Insert Data to Firebase Realtime Database

sendMessage() {
    _firebaseRef.push()<span class="hljs-meta">.set</span>({
        <span class="hljs-string">"message"</span>: _txtCtrl<span class="hljs-meta">.text</span>,
        <span class="hljs-string">"timestamp"</span>: DateTime.now().millisecondsSinceEpoch
    })<span class="hljs-comment">;</span>
}

this code can insert(push) data into firebase

Delete Data to Firebase Realtime Database

deleteMessage<span class="hljs-comment">(key)</span> {
    _firebaseRef.child<span class="hljs-comment">(key)</span>.remove<span class="hljs-comment">()</span>;
}

Using this code, we delete child with key

Update Data to Firebase Realtime Database

updateTimeStamp(<span class="hljs-built_in">key</span>) {
    _firebaseRef
        .child(<span class="hljs-built_in">key</span>)
        .<span class="hljs-keyword">update</span>({<span class="hljs-string">"timestamp"</span>: DateTime.now().millisecondsSinceEpoch});
}

Using this code, we’re updating the timestamp of particular message based on key

Read data from firebase Realtime Database

To display firebase data into our app, we need StreamBuilder.

StreamBuilder(
    <span class="hljs-name">stream</span>: _firebaseRef.onValue,
    builder: (<span class="hljs-name">context</span>, snap) {

        if (<span class="hljs-name">snap</span>.hasData <span class="hljs-symbol">&&</span> !snap.hasError <span class="hljs-symbol">&&</span> snap.data.snapshot.value != null) {

            Map data = snap.data.snapshot.value<span class="hljs-comment">;</span>
            List item = []<span class="hljs-comment">;</span>

            data.forEach((<span class="hljs-name">index</span>, data) => item.add({<span class="hljs-string">"key"</span>: index, ...data}))<span class="hljs-comment">;</span>

            return ListView.builder(
                    <span class="hljs-name">itemCount</span>: item.length,
                    itemBuilder: (<span class="hljs-name">context</span>, index) {
                    return ListTile(
                        <span class="hljs-name">title</span>: Text(<span class="hljs-name">item</span>[index]['message']),
                        trailing: Text(<span class="hljs-name">DateFormat</span>(<span class="hljs-string">"hh:mm:ss"</span>)
                            .format(<span class="hljs-name">DateTime</span>.fromMicrosecondsSinceEpoch(
                                <span class="hljs-name">item</span>[index]['timestamp'] * 1000))
                            .toString()),
                        onTap: () =>
                            updateTimeStamp(item[index]['key']),
                        onLongPress: () =>
                            deleteMessage(item[index]['key']),
                    );
                    },
                );
        }
        else
            return Text("No data");
    },
)

Explanation:

  • We created StreamBuilder based on _firebaseRef.onValue, which means, we update stream builder whenever data changes on firebase (CRUD)
  • If there is an error with data or null, we display Text Widget with “No data”
  • If there is no error, we’re storing all messages (snap.data.snapshot.value) into Map data
  • Since firebase key are unpredictable, we have used forEach to push data into item

    Before

      {-Lk30mSI-<span class="hljs-string">ObTUuy730c4:</span> {<span class="hljs-string">message:</span> gbrjv dl, <span class="hljs-string">timestamp:</span> <span class="hljs-number">1563435680036</span>}, -<span class="hljs-string">Lk30mXd97oFihH_5MVR:</span> {<span class="hljs-string">message:</span> gbrjv dl, <span class="hljs-string">timestamp:</span> <span class="hljs-number">1563435679414</span>}, -Lk30izl-<span class="hljs-string">cQ7IdtKeo4i:</span> {<span class="hljs-string">message:</span> ghrhr, <span class="hljs-string">timestamp:</span> <span class="hljs-number">1563435678204</span>}}
    

    After

      [{<span class="hljs-string">key:</span> -Lk30mSI-ObTUuy730c4, <span class="hljs-string">message:</span> gbrjv dl, <span class="hljs-string">timestamp:</span> <span class="hljs-number">1563435680036</span>}, {<span class="hljs-string">key:</span> -Lk30mXd97oFihH_5MVR, <span class="hljs-string">message:</span> gbrjv dl, <span class="hljs-string">timestamp:</span> <span class="hljs-number">1563435679414</span>}, {<span class="hljs-string">key:</span> -Lk30izl-cQ7IdtKeo4i, <span class="hljs-string">message:</span> ghrhr, <span class="hljs-string">timestamp:</span> <span class="hljs-number">1563435678204</span>}]
    
  • Once everything is fine, we use ListView.builder() & ListTile for displaying data
  • When user Tap, we update timestamp & with longpress, we delete data

This code we display a TextField with Buttons

Container( <span class="hljs-name">child</span>: Row(<span class="hljs-name">children</span>: <Widget>[
        Expanded(<span class="hljs-name">child</span>: TextField(<span class="hljs-name">controller</span>: _txtCtrl)),
        SizedBox(
            <span class="hljs-name">width</span>: <span class="hljs-number">80</span>,
            child: OutlineButton(<span class="hljs-name">child</span>: Text(<span class="hljs-string">"Add"</span>), onPressed: () => sendMessage()))
    ])
)<span class="hljs-comment">;</span>

Screenshot