Back to blog

Feb 09, 2025

Tìm hiểu flutter - cách làm 1 ứng dụng mobile CRUD đơn giản (phần 2)

PH

Phineas

@Phineas

cover

Ở bài viết trước, chúng ta đã tìm hiểu về flutter và cách cài đặt flutter với firebase.

Tiếp tục cho phần này, chúng ta cùng làm 1 ứng dụng CRUD đơn giản nhé.

Bước 1: Cầu hình firebase trong flutter

Mở tệp 'lib/main.dart' và cập nhật như sau:

dart
import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:cloud_firestore/cloud_firestore.dart';

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

class MyApp extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Todo App',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: TodoListPage(),
    );
  }
}

class TodoListPage extends StatefulWidget {
  
  _TodoListPageState createState() => _TodoListPageState();
}

class _TodoListPageState extends State<TodoListPage> {
  final TextEditingController _controller = TextEditingController();

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Todo List'),
      ),
      body: Column(
        children: <Widget>[
          Padding(
            padding: EdgeInsets.all(8.0),
            child: Row(
              children: <Widget>[
                Expanded(
                  child: TextField(
                    controller: _controller,
                    decoration: InputDecoration(
                      hintText: 'Enter a new task',
                    ),
                  ),
                ),
                ElevatedButton(
                  onPressed: () {
                    if (_controller.text.isNotEmpty) {
                      FirebaseFirestore.instance.collection('todos').add({
                        'task': _controller.text,
                        'timestamp': FieldValue.serverTimestamp(),
                      });
                      _controller.clear();
                    }
                  },
                  child: Text('Add'),
                ),
              ],
            ),
          ),
          Expanded(
            child: StreamBuilder(
              stream: FirebaseFirestore.instance.collection('todos').snapshots(),
              builder: (context, AsyncSnapshot<QuerySnapshot> snapshot) {
                if (!snapshot.hasData) return Center(child: CircularProgressIndicator());
                return ListView.builder(
                  itemCount: snapshot.data!.docs.length,
                  itemBuilder: (context, index) {
                    var todo = snapshot.data!.docs[index];
                    return ListTile(
                      title: Text(todo['task']),
                      trailing: IconButton(
                        icon: Icon(Icons.delete),
                        onPressed: () {
                          FirebaseFirestore.instance
                              .collection('todos')
                              .doc(todo.id)
                              .delete();
                        },
                      ),
                    );
                  },
                );
              },
            ),
          ),
        ],
      ),
    );
  }
}

Giao diện sẽ trong như thế này:

Bước 2: CRUD Hoàn Chỉnh

Đã được thực hiện trong nút "Add" ở bước trên. Khi người dùng nhập công việc và nhấn "Add", công việc mới sẽ được thêm vào Firestore.

Tạo (Create)

Đã được thực hiện trong nút "Add" ở bước trên. Khi người dùng nhập công việc và nhấn "Add", công việc mới sẽ được thêm vào Firestore.

Đọc (Read)

Sử dụng StreamBuilder để lắng nghe các thay đổi từ Firestore và cập nhật danh sách todo.

Cập Nhật (Update)

Để cập nhật một công việc, bạn có thể mở một dialog khi nhấn vào công việc và cho phép người dùng chỉnh sửa nó:

javascript
void _updateTask(DocumentSnapshot todo) {
  _controller.text = todo['task'];
  showDialog(
    context: context,
    builder: (context) {
      return AlertDialog(
        title: Text('Update Task'),
        content: TextField(
          controller: _controller,
        ),
        actions: <Widget>[
          ElevatedButton(
            onPressed: () {
              FirebaseFirestore.instance.collection('todos').doc(todo.id).update({
                'task': _controller.text,
                'timestamp': FieldValue.serverTimestamp(),
              });
              _controller.clear();
              Navigator.of(context).pop();
            },
            child: Text('Update'),
          ),
        ],
      );
    },
  );
}

Thêm nút để gọi _updateTask khi nhấn vào công việc:

javascript
ListTile(
  title: Text(todo['task']),
  trailing: Row(
    mainAxisSize: MainAxisSize.min,
    children: <Widget>[
      IconButton(
        icon: Icon(Icons.edit),
        onPressed: () {
          _updateTask(todo);
        },
      ),
      IconButton(
        icon: Icon(Icons.delete),
        onPressed: () {
          FirebaseFirestore.instance.collection('todos').doc(todo.id).delete();
        },
      ),
    ],
  ),
)

Xóa (Delete)

Đã được thực hiện với nút delete ở bước trên. Khi nhấn vào biểu tượng delete, công việc sẽ bị xóa khỏi Firestore.

Kết Luận

Vậy là mình đã hoàn thành một ứng dụng Todo đơn giản sử dụng Flutter và Firebase với các chức năng CRUD. Bây giờ các bạn có thể mở rộng ứng dụng này bằng cách thêm các tính năng như xác thực người dùng, nhắc nhở task, thông báo và nhiều tính năng khác.

Hy vọng bài viết này giúp ích cho bạn trong quá trình học tập và phát triển ứng dụng Flutter. Chúc bạn thành công!