Quay lại danh sách bài viết

Kết Nối Ứng Dụng Flutter Với API Node.js

30 tháng 11, 2025
admin
Kết Nối Ứng Dụng Flutter Với API Node.js
# Kết Nối Ứng Dụng Flutter Với API Node.js Flutter, một UI toolkit đến từ Google, cho phép xây dựng ứng dụng mobile, web và desktop đẹp và native từ một codebase duy nhất. Node.js là một runtime environment cho JavaScript ở phía server, rất phổ biến để xây dựng các API nhanh và có khả năng mở rộng. Việc kết hợp sức mạnh của Flutter ở frontend và Node.js ở backend tạo nên một stack phát triển hiện đại và hiệu quả. Bài viết này sẽ đi sâu vào cách ứng dụng Flutter của bạn có thể giao tiếp với API được xây dựng bằng Node.js, tập trung vào việc thực hiện các yêu cầu HTTP và xử lý dữ liệu. ![Sơ đồ kiến trúc tổng thể](/img/flutter-nodejs-architecture.svg) ## 1. Thiết lập môi trường Trước khi bắt đầu code, chúng ta cần đảm bảo môi trường phát triển đã sẵn sàng. ### 1.1 Chuẩn bị API Node.js Để làm theo hướng dẫn này, bạn cần có một API Node.js đang chạy và có thể truy cập được. Nếu bạn chưa có, bạn có thể tạo một API cơ bản rất nhanh với Express.js. Dưới đây là ví dụ về một API Node.js đơn giản trả về danh sách người dùng và cho phép thêm người dùng mới: ```javascript const express = require('express'); const bodyParser = require('body-parser'); const cors = require('cors'); // Cần thiết nếu chạy Flutter app trên giả lập/thiết bị khác với server const app = express(); const port = 3000; // Middleware app.use(cors()); app.use(bodyParser.json()); // Dữ liệu giả let users = [ { id: 1, name: 'Alice' }, { id: 2, name: 'Bob' } ]; // GET request để lấy tất cả người dùng app.get('/api/users', (req, res) => { res.json(users); }); // POST request để thêm người dùng mới app.post('/api/users', (req, res) => { const newUser = req.body; if (!newUser || !newUser.name) { return res.status(400).json({ message: 'Name is required' }); } newUser.id = users.length + 1; // Tạo ID đơn giản users.push(newUser); res.status(201).json(newUser); }); // Khởi chạy server app.listen(port, () => { console.log(`Node.js API listening at http://localhost:${port}`); }); ``` Lưu đoạn code trên vào một file (ví dụ: `server.js`), cài đặt các dependencies (`npm install express body-parser cors`) và chạy nó (`node server.js`). Đảm bảo API chạy trên một địa chỉ và cổng mà thiết bị Flutter của bạn có thể truy cập (ví dụ: `http://10.0.2.2:3000` nếu chạy trên Android emulator và server trên `localhost`). ### 1.2 Thiết lập Project Flutter Nếu bạn đã có project Flutter, hãy mở file `pubspec.yaml`. Nếu chưa, tạo project mới bằng `flutter create your_app_name`. Chúng ta sẽ sử dụng package `http` để đơn giản. Thêm `http` vào phần `dependencies` trong `pubspec.yaml`: ```yaml dependencies: flutter: sdk: flutter cupertino_icons: ^1.0.2 # Thêm package http tại đây http: ^0.13.3 # Hoặc phiên bản mới nhất dev_dependencies: flutter_test: sdk: flutter flutter_lints: ^2.0.0 flutter: uses-material-design: true ``` Sau khi thêm, chạy lệnh `flutter pub get` trong terminal của project Flutter để cài đặt package. ## 2. Thực hiện HTTP Request từ Flutter Package `http` cung cấp các phương thức dễ sử dụng để thực hiện các yêu cầu HTTP phổ biến như GET, POST, PUT, DELETE. Trước tiên, import package `http` và `dart:convert` (để xử lý JSON) vào file Dart của bạn: ```dart import 'package:http/http.dart' as http; import 'dart:convert'; ``` ![Luồng HTTP Request và Response](/img/http-request-response-flow.svg) ### 2.1 GET Request: Lấy dữ liệu Để lấy danh sách người dùng từ API Node.js ví dụ ở trên, bạn có thể tạo một hàm bất đồng bộ sử dụng `http.get()`: ```dart Future<List<dynamic>> fetchUsers() async { final response = await http.get(Uri.parse('YOUR_NODEJS_API_URL/api/users')); if (response.statusCode == 200) { // Nếu server trả về mã status 200 OK, parse JSON return jsonDecode(response.body); // response.body là chuỗi JSON } else { // Nếu không thành công, throw một exception. throw Exception('Failed to load users'); } } ``` Bạn cần thay thế `'YOUR_NODEJS_API_URL'` bằng địa chỉ IP và cổng thực tế của API Node.js server của bạn. ### 2.2 POST Request: Gửi dữ liệu Để thêm một người dùng mới, bạn sử dụng phương thức `http.post()`. Bạn cần cung cấp URL, headers (để thông báo định dạng dữ liệu gửi đi là JSON) và body (dữ liệu cần gửi, đã được encode sang chuỗi JSON). ```dart Future<void> createUser(String name) async { final response = await http.post( Uri.parse('YOUR_NODEJS_API_URL/api/users'), headers: <String, String>{ 'Content-Type': 'application/json; charset=UTF-8', }, body: jsonEncode(<String, String>{'name': name}), ); if (response.statusCode == 201) { // Nếu server trả về mã status 201 Created print('User created successfully: ${response.body}'); } else { // Nếu không thành công, throw một exception. throw Exception('Failed to create user: ${response.statusCode}'); } } ``` ![Sơ đồ luồng truyền và xử lý dữ liệu](/img/data-flow.svg) ## 3. Xử lý bất đồng bộ với Async/Await Các thao tác mạng trong Flutter (và Dart) là bất đồng bộ. Điều này có nghĩa là chúng không chặn luồng chính của ứng dụng, giúp UI luôn mượt mà. Từ khóa `async` và `await` là cách hiện đại và dễ đọc để làm việc với các thao tác bất đồng bộ. * `async`: Được đặt trước một hàm để báo hiệu rằng hàm đó sẽ thực hiện các thao tác bất đồng bộ. * `await`: Được sử dụng bên trong một hàm `async` để chờ kết quả của một Future mà không chặn toàn bộ luồng thực thi. Khi gặp `await`, hàm sẽ tạm dừng, giải phóng CPU để làm việc khác, và sẽ tiếp tục chạy khi Future hoàn thành. Các ví dụ `fetchUsers` và `createUser` ở trên đều sử dụng `async/await` để chờ kết quả từ `http.get` và `http.post`. ## 4. Xử lý lỗi và phản hồi cho người dùng Việc xử lý lỗi API là rất quan trọng để ứng dụng của bạn ổn định và cung cấp phản hồi rõ ràng cho người dùng. Luôn bọc các lệnh gọi API trong khối `try-catch`. ```dart void _loadUsers() async { try { List<dynamic> usersList = await fetchUsers(); // Cập nhật UI với dữ liệu người dùng print('Fetched ${usersList.length} users.'); // setState(() { _users = usersList; }); // Ví dụ cập nhật state } catch (e) { // Xử lý lỗi và thông báo cho người dùng print('Error fetching users: $e'); // ScaffoldMessenger.of(context).showSnackBar(...); // Ví dụ hiển thị thông báo lỗi } } void _addUser(String name) async { try { await createUser(name); print('User added successfully.'); // Có thể fetch lại danh sách người dùng sau khi thêm thành công // _loadUsers(); // ScaffoldMessenger.of(context).showSnackBar(...); // Ví dụ hiển thị thông báo thành công } catch (e) { print('Error adding user: $e'); // ScaffoldMessenger.of(context).showSnackBar(...); // Ví dụ hiển thị thông báo lỗi } } ``` Khi server trả về mã trạng thái lỗi (ví dụ: 400, 404, 500), phương thức `http.get` hoặc `http.post` sẽ không tự động throw lỗi. Bạn cần kiểm tra thuộc tính `statusCode` của response và throw exception một cách thủ công nếu cần xử lý trong khối `catch`. ## 5. Best Practices * **Sử dụng biến môi trường:** Không nên hardcode URL API trong code. Sử dụng các package như `flutter_dotenv` để quản lý biến môi trường. * **Mô hình hóa dữ liệu:** Thay vì làm việc trực tiếp với `dynamic` hoặc `Map<String, dynamic>`, hãy tạo các Dart class để mô hình hóa dữ liệu nhận được từ API (sử dụng `json_serializable` giúp tự động hóa). * **Xử lý lỗi chi tiết:** Phân loại các loại lỗi (lỗi mạng, lỗi server, lỗi parsing) và cung cấp thông báo cụ thể cho người dùng. * **Sử dụng Dio thay vì http (Tùy chọn):** Đối với các ứng dụng lớn hơn, package `dio` thường được ưa chuộng hơn `http` vì nó cung cấp nhiều tính năng hơn như interceptors, global configuration, form data, request cancellation, v.v. * **Bảo mật:** Đảm bảo kết nối API của bạn an toàn (sử dụng HTTPS). Xử lý xác thực và ủy quyền đúng cách. ## Kết luận Kết nối ứng dụng Flutter với API Node.js là một tác vụ phổ biến khi xây dựng các ứng dụng full-stack. Bằng cách hiểu rõ cách thực hiện HTTP requests, xử lý bất đồng bộ và quản lý lỗi trong Flutter, bạn có thể dễ dàng tích hợp ứng dụng mobile của mình với backend Node.js mạnh mẽ, mở ra nhiều khả năng phát triển ứng dụng. ## Tài Liệu Tham Khảo - [Flutter Documentation: Fetch data from the internet](https://flutter.dev/docs/cookbook/networking/fetch-data) - [Node.js Documentation](https://nodejs.org/docs) - [Express.js Documentation](https://expressjs.com/) - [http package](https://pub.dev/packages/http) - [dio package](https://pub.dev/packages/dio) - [json_serializable package](https://pub.dev/packages/json_serializable) - [flutter_dotenv package](https://pub.dev/packages/flutter_dotenv)
flutter
nodejs
api
mobile
backend
Chia sẻ:

Bài viết liên quan

Supabase - Nền Tảng Backend-as-a-Service Hiện Đại

Supabase - Nền Tảng Backend-as-a-Service Hiện Đại <div className="search-container"> <input type="text" placeholder="Tìm kiếm trong bà...

REST API vs GraphQL: So sánh và lựa chọn

REST API vs GraphQL: So sánh và lựa chọn Trong thời đại phát triển ứng dụng web hiện đại, việc lựa chọn kiến trúc API phù hợp là một quyết định qua...

Node.js - Nền Tảng JavaScript Runtime Hiện Đại

Node.js - Nền Tảng JavaScript Runtime Hiện Đại <div className="search-container"> <input type="text" placeholder="Tìm kiếm trong bài v...