0
0
Fluttermobile~20 mins

Realtime Database in Flutter - Mini App: Build & Ship

Choose your learning style9 modes available
Build: Realtime Todo List
A simple todo list app screen that syncs tasks in real-time using Firebase Realtime Database. Users can add new tasks, see the list update instantly, and remove tasks.
Target UI
-------------------------
| Realtime Todo List     |
|-----------------------|
| + Add Task             |
|-----------------------|
| [ ] Buy groceries      |
| [ ] Walk the dog       |
| [ ] Call mom           |
|-----------------------|
Connect to Firebase Realtime Database
Display a list of todo tasks fetched in real-time
Add new tasks with a TextField and a button
Remove tasks by tapping on them
Update the UI instantly when database changes
Starter Code
Flutter
import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_database/firebase_database.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Realtime Todo List',
      home: const TodoScreen(),
    );
  }
}

class TodoScreen extends StatefulWidget {
  const TodoScreen({super.key});

  @override
  State<TodoScreen> createState() => _TodoScreenState();
}

class _TodoScreenState extends State<TodoScreen> {
  final DatabaseReference _todoRef = FirebaseDatabase.instance.ref('todos');
  final TextEditingController _controller = TextEditingController();

  // TODO: Add code to listen to realtime updates and display list
  // TODO: Add code to add new todo
  // TODO: Add code to remove todo

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Realtime Todo List')),
      body: Column(
        children: [
          Padding(
            padding: const EdgeInsets.all(8.0),
            child: Row(
              children: [
                Expanded(
                  child: TextField(
                    controller: _controller,
                    decoration: const InputDecoration(
                      labelText: 'New Task',
                    ),
                  ),
                ),
                IconButton(
                  icon: const Icon(Icons.add),
                  onPressed: () {
                    // TODO: Add new task to database
                  },
                ),
              ],
            ),
          ),
          Expanded(
            child: Center(
              child: Text('Loading tasks...'),
            ),
          ),
        ],
      ),
    );
  }
}
Task 1
Task 2
Task 3
Task 4
Solution
Flutter
import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_database/firebase_database.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Realtime Todo List',
      home: const TodoScreen(),
    );
  }
}

class TodoScreen extends StatefulWidget {
  const TodoScreen({super.key});

  @override
  State<TodoScreen> createState() => _TodoScreenState();
}

class _TodoScreenState extends State<TodoScreen> {
  final DatabaseReference _todoRef = FirebaseDatabase.instance.ref('todos');
  final TextEditingController _controller = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Realtime Todo List')),
      body: Column(
        children: [
          Padding(
            padding: const EdgeInsets.all(8.0),
            child: Row(
              children: [
                Expanded(
                  child: TextField(
                    controller: _controller,
                    decoration: const InputDecoration(
                      labelText: 'New Task',
                    ),
                  ),
                ),
                IconButton(
                  icon: const Icon(Icons.add),
                  onPressed: () {
                    final text = _controller.text.trim();
                    if (text.isNotEmpty) {
                      _todoRef.push().set({'task': text});
                      _controller.clear();
                    }
                  },
                ),
              ],
            ),
          ),
          Expanded(
            child: StreamBuilder<DatabaseEvent>(
              stream: _todoRef.onValue,
              builder: (context, snapshot) {
                if (snapshot.hasData && snapshot.data!.snapshot.value != null) {
                  final data = Map<String, dynamic>.from(snapshot.data!.snapshot.value as Map);
                  final tasks = data.entries.toList();
                  return ListView.builder(
                    itemCount: tasks.length,
                    itemBuilder: (context, index) {
                      final key = tasks[index].key;
                      final task = tasks[index].value['task'] as String;
                      return ListTile(
                        title: Text(task),
                        onTap: () {
                          _todoRef.child(key).remove();
                        },
                      );
                    },
                  );
                } else if (snapshot.hasError) {
                  return Center(child: Text('Error loading tasks'));
                } else {
                  return const Center(child: CircularProgressIndicator());
                }
              },
            ),
          ),
        ],
      ),
    );
  }
}

This app connects to Firebase Realtime Database and listens to the 'todos' node using onValue stream. When data changes, the UI updates instantly showing the current list of tasks.

Users can add new tasks by typing in the TextField and pressing the '+' button. This pushes a new child with the task text to the database.

Tapping a task removes it from the database, which also updates the UI in real-time.

This shows how easy it is to build a live-updating app with Firebase Realtime Database and Flutter.

Final Result
Completed Screen
-------------------------
| Realtime Todo List     |
|-----------------------|
| + Add Task             |
|-----------------------|
| Buy groceries          |
| Walk the dog           |
| Call mom               |
|-----------------------|
User types a task in the text field and taps '+' to add it to the list instantly.
The list updates live when tasks are added or removed by any user.
Tapping a task removes it from the list and database immediately.
Stretch Goal
Add a confirmation dialog before deleting a task.
💡 Hint
Use showDialog with AlertDialog to ask user to confirm before calling remove() on the task.