Using Firebase Realtime Database in Flutter

Flutter, Google’s UI toolkit, makes it easier to build natively compiled applications for mobile, web, and desktop from a single codebase. When developing real-time applications, a real-time database like Firebase Realtime Database can be an excellent choice. This guide will walk you through how to use Firebase Realtime Database in your Flutter applications.

What is Firebase Realtime Database?

Firebase Realtime Database is a cloud-hosted, NoSQL database that lets you store and synchronize data between your users in real-time. The data is stored as one large JSON tree, and clients connected to the database receive automatic updates with the newest data.

Why Use Firebase Realtime Database with Flutter?

  • Real-time Data: Offers immediate data synchronization across all connected devices.
  • Scalability: Automatically scales to meet your app’s needs.
  • Offline Capabilities: Caches data locally for offline access.
  • Ease of Use: Simple API for reading and writing data.

How to Implement Firebase Realtime Database in Flutter

To implement Firebase Realtime Database in Flutter, follow these steps:

Step 1: Set up Firebase Project

  1. Go to the Firebase Console and create a new project.
  2. Follow the setup steps, and enable Realtime Database in your Firebase project.

Step 2: Add Firebase to Your Flutter App

  1. Install the Firebase CLI:
  2. npm install -g firebase-tools
    firebase login
  3. Create a Flutter Project:
  4. flutter create flutter_realtime_db_app
    cd flutter_realtime_db_app
  5. Add Firebase Core and Realtime Database dependencies to pubspec.yaml:
  6. dependencies:
      flutter:
        sdk: flutter
      firebase_core: ^2.15.0
      firebase_database: ^10.2.0
  7. Run flutter pub get to install the dependencies.

Step 3: Configure Firebase in Your Flutter App

  1. Initialize Firebase in your Flutter app:
  2. In your main.dart file, add the following code:

    
    import 'package:flutter/material.dart';
    import 'package:firebase_core/firebase_core.dart';
    import 'firebase_options.dart';
    
    void main() async {
      WidgetsFlutterBinding.ensureInitialized();
      await Firebase.initializeApp(
        options: DefaultFirebaseOptions.currentPlatform,
      );
      runApp(MyApp());
    }
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Firebase Realtime DB Demo',
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: MyHomePage(title: 'Firebase Realtime DB Home Page'),
        );
      }
    }
    
    class MyHomePage extends StatelessWidget {
      MyHomePage({Key? key, required this.title}) : super(key: key);
    
      final String title;
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text(title),
          ),
          body: Center(
            child: Text('Firebase initialized!'),
          ),
        );
      }
    }
    
  3. Ensure that you have generated the firebase_options.dart file by running:
  4. flutterfire configure

Step 4: Write Data to Firebase Realtime Database

  1. Import necessary packages:
  2. import 'package:firebase_database/firebase_database.dart';
  3. Write data to the database:
  4. final databaseReference = FirebaseDatabase.instance.ref();
    
    void createData() {
      databaseReference.child("users").child("123").set({
        'name': 'John Doe',
        'email': 'john.doe@example.com'
      });
    }
  5. Integrate the write function in your UI:
  6. ElevatedButton(
      onPressed: () {
        createData();
      },
      child: Text('Create Data'),
    )

Step 5: Read Data from Firebase Realtime Database

  1. Read data from the database:
  2. void readData() {
      databaseReference.child("users/123").get().then((snapshot) {
        if (snapshot.exists) {
          print('Data: ${snapshot.value}');
        } else {
          print('No data available.');
        }
      }).catchError((error) {
        print('Error: $error');
      });
    }
  3. Integrate the read function in your UI:
  4. ElevatedButton(
      onPressed: () {
        readData();
      },
      child: Text('Read Data'),
    )

Step 6: Update Data in Firebase Realtime Database

  1. Update data in the database:
  2. void updateData() {
      databaseReference.child("users/123").update({
        'email': 'john.newemail@example.com',
        'name': 'John A. Doe',
      });
    }
  3. Integrate the update function in your UI:
  4. ElevatedButton(
      onPressed: () {
        updateData();
      },
      child: Text('Update Data'),
    )

Step 7: Delete Data in Firebase Realtime Database

  1. Delete data from the database:
  2. void deleteData() {
      databaseReference.child("users/123").remove().then((_) {
        print('Data deleted successfully');
      }).catchError((error) {
        print('Error deleting data: $error');
      });
    }
  3. Integrate the delete function in your UI:
  4. ElevatedButton(
      onPressed: () {
        deleteData();
      },
      child: Text('Delete Data'),
    )

Step 8: Real-time Data Listening

  1. Listen for real-time data changes:
  2. void listenForChanges() {
      databaseReference.child("users").onValue.listen((event) {
        if (event.snapshot.exists) {
          print('Data updated: ${event.snapshot.value}');
        } else {
          print('No data available.');
        }
      });
    }
  3. Call the listen function in your initState or relevant places:
  4. @override
    void initState() {
      super.initState();
      listenForChanges();
    }

Complete Example

Here’s a complete example integrating all the above functionalities in a single Flutter widget:


import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_database/firebase_database.dart';
import 'firebase_options.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Firebase Realtime DB Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Firebase Realtime DB Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

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

class _MyHomePageState extends State<MyHomePage> {
  final databaseReference = FirebaseDatabase.instance.ref();
  String data = 'No data';

  @override
  void initState() {
    super.initState();
    listenForChanges();
  }

  void createData() {
    databaseReference.child("users").child("123").set({
      'name': 'John Doe',
      'email': 'john.doe@example.com'
    });
  }

  void readData() {
    databaseReference.child("users/123").get().then((snapshot) {
      if (snapshot.exists) {
        setState(() {
          data = 'Data: ${snapshot.value}';
        });
        print('Data: ${snapshot.value}');
      } else {
        print('No data available.');
      }
    }).catchError((error) {
      print('Error: $error');
    });
  }

  void updateData() {
    databaseReference.child("users/123").update({
      'email': 'john.newemail@example.com',
      'name': 'John A. Doe',
    });
  }

  void deleteData() {
    databaseReference.child("users/123").remove().then((_) {
      print('Data deleted successfully');
    }).catchError((error) {
      print('Error deleting data: $error');
    });
  }

  void listenForChanges() {
    databaseReference.child("users").onValue.listen((event) {
      if (event.snapshot.exists) {
        setState(() {
          data = 'Data updated: ${event.snapshot.value}';
        });
        print('Data updated: ${event.snapshot.value}');
      } else {
        print('No data available.');
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text(data),
            ElevatedButton(
              onPressed: () {
                createData();
              },
              child: Text('Create Data'),
            ),
            ElevatedButton(
              onPressed: () {
                readData();
              },
              child: Text('Read Data'),
            ),
            ElevatedButton(
              onPressed: () {
                updateData();
              },
              child: Text('Update Data'),
            ),
            ElevatedButton(
              onPressed: () {
                deleteData();
              },
              child: Text('Delete Data'),
            ),
          ],
        ),
      ),
    );
  }
}

Conclusion

Firebase Realtime Database offers a powerful and convenient solution for managing real-time data in Flutter applications. With its simple API and real-time capabilities, developers can easily create interactive and dynamic user experiences. This guide has covered the essential steps for integrating Firebase Realtime Database into your Flutter projects, enabling you to build scalable and real-time applications with ease.