Giới thiệu dự án
Sự bùng nổ của thị trường thiết bị di động trong thập kỷ qua đã xác lập vị thế thống trị tuyệt đối của hai hệ điều hành: Android (chiếm hơn 70% thị phần toàn cầu) và iOS (chiếm gần 28%). Sự phân mảnh này tạo ra một rào cản kỹ thuật và kinh tế lớn cho các tổ chức, doanh nghiệp: việc duy trì song song hai đội ngũ phát triển riêng biệt cho Native Android (Java/Kotlin) và Native iOS (Objective-C/Swift) làm tăng chi phí phát triển lên 80-100%, kéo dài thời gian ra mắt sản phẩm (Time-to-Market) và gây khó khăn trong việc đồng bộ hóa tính năng.
Đề tài "Tìm hiểu về Flutter và ứng dụng" do sinh viên Đỗ Thế Hiệp thực hiện dưới sự hướng dẫn của TS. Đỗ Văn Chiểu tại Trường Đại học Quản lý và Công nghệ Hải Phòng tập trung giải quyết bài toán tối ưu hóa quy trình phát triển phần mềm đa nền tảng (Cross-platform Development). Đề tài nghiên cứu sâu về kiến trúc SDK Flutter của Google, ngôn ngữ Dart và triển khai ứng dụng thực nghiệm chuyển đổi thông tin số từ hệ thống Website (cụ thể là Website Hợp tác xã Nông nghiệp và Du lịch Cộng đồng Cổ Loa) lên nền tảng di động cho cả hai hệ điều hành iOS và Android.
+-----------------------------------------------------------------------+
| DỰ ÁN FLUTTER |
+-----------------------------------------------------------------------+
| Mục tiêu 1: Làm chủ kiến trúc Flutter SDK & Ngôn ngữ lập trình Dart |
| Mục tiêu 2: Thiết kế kiến trúc đa nền tảng tối ưu hiệu năng đồ họa |
| Mục tiêu 3: Triển khai CRUD Database cục bộ (SQLite) & Cloud (NoSQL) |
| Mục tiêu 4: Đóng gói và biên dịch ứng dụng di động cho Android & iOS |
+-----------------------------------------------------------------------+
Mục tiêu đề tài
- Nghiên cứu cơ chế hoạt động cốt lõi của Flutter Framework: Phân tích cơ chế kết xuất đồ họa độc lập Skia Engine, bộ biên dịch kép AOT (Ahead Of Time) và JIT (Just In Time), hệ thống Widget Tree và cơ chế phản ứng trạng thái (Reactive State Management).
- Làm chủ ngôn ngữ lập trình Dart: Khảo sát cú pháp hướng đối tượng (OOP), hệ thống phân loại kiểu dữ liệu tĩnh nghiêm ngặt (Strongly Typed), Type Inference, quản lý luồng bất đồng bộ và xử lý bộ nhớ.
- Hiện thực hóa mô hình quản trị dữ liệu: Xây dựng kiến trúc lưu trữ dữ liệu cục bộ với SQLite thông qua plugin
sqflite và mô hình dữ liệu thời gian thực với Cloud Firestore / Firebase.
- Triển khai ứng dụng thực nghiệm: Thiết kế, xây dựng và tối ưu hóa ứng dụng di động đọc thông tin website, tích hợp WebView, cấu hình Splash Screen, App Icon và xử lý quy trình đóng gói đa nền tảng trên Windows và macOS.
Phạm vi và giới hạn đề tài
- Phạm vi nghiên cứu: Flutter SDK 2.x, Dart 2.12+, hệ điều hành Android (Android 5.0 Lollipop đến Android 11/12) và iOS (iOS 11 đến iOS 14.x).
- Phạm vi ứng dụng: Đọc và hiển thị nội dung động, tối ưu giao diện Material Design cho Android và Cupertino Style cho iOS; tích hợp cơ chế điều hướng Navigation và quản lý trạng thái cục bộ/toàn cục.
- Giới hạn: Ứng dụng thực nghiệm tập trung vào luồng chuyển đổi nội dung số hóa từ Web sang Mobile App, chưa đi sâu vào việc viết Custom Platform Channels bằng Native C++/Java/Objective-C phức tạp.
Phân tích và thiết kế giải pháp
Phân tích hiện trạng
Trước khi Flutter ra đời, việc phát triển ứng dụng di động phân nhánh thành hai trường phái chính: Native Development và Hybrid/Web-view Bridge Development.
| Tiêu chí |
Native (Java/Kotlin, Swift) |
Hybrid Bridge (React Native, Cordova) |
Giải pháp Flutter (Dart + Skia) |
| Cơ chế kết xuất (Rendering) |
Native OEM Widgets |
JavaScript Bridge qua Native UI |
Skia/Impeller Engine tự vẽ trực tiếp 2D |
| Tốc độ khung hình (Frame Rate) |
Cố định 60 - 120 FPS |
45 - 60 FPS (thường nghẽn ở JS Bridge) |
Ổn định 60 FPS mượt mà |
| Codebase |
Tách biệt (2 codebases) |
Đơn nhất (1 codebase) |
Đơn nhất (1 codebase duy nhất) |
| Thời gian biên dịch & sửa lỗi |
Chậm (Full recompile 1-3 phút) |
Nhanh (Fast Refresh qua JS) |
Cực nhanh (< 1 giây với State Hot Reload) |
| Mức tiêu hao tài nguyên |
Thấp |
Trung bình - Cao (do nạp runtime JS) |
Tối ưu (Biên dịch trực tiếp ra Machine Code) |
Đánh giá yêu cầu theo mô hình MoSCoW
- Must have (Bắt buộc phải có):
- Khả năng biên dịch và thực thi đồng nhất trên cả hai hệ điều hành Android (.apk) và iOS (.ipa).
- Bộ điều hướng phân tầng (Navigation Stack) hỗ trợ
push() và pop().
- Tích hợp xử lý cử chỉ người dùng (
GestureDetector: Tap, Double Tap, Drag, Pan, Long Press, Pinch).
- Khả năng lưu trữ và đồng bộ dữ liệu ngoại tuyến (Offline-first) bằng SQLite.
- Should have (Nên có):
- Cơ chế State Management tách biệt giữa Ephemeral State và App State thông qua
ChangeNotifierProvider.
- Hệ thống giao diện thích ứng giao diện người dùng theo chuẩn Material Design và Cupertino.
- Could have (Có thể có):
- Tích hợp cơ sở dữ liệu NoSQL đám mây Firebase Realtime Database.
- Tích hợp Webview điều hướng nhúng trang tin tức Hợp tác xã Cổ Loa.
- Won't have (Chưa thực hiện):
- Hệ thống thanh toán trực tuyến đa kênh (In-app Purchase / Payment Gateway).
Thiết kế hệ thống
Kiến trúc phần mềm của giải pháp xây dựng trên mô hình phân lớp chuẩn của Flutter, chia thành 3 tầng chức năng độc lập:
+-------------------------------------------------------------------------+
| FRAMEWORK LAYER (Ngôn ngữ Dart) |
| - Material Design Widgets / Cupertino Widgets |
| - Widgets Layer: Text, Image, Column, Row, Stack, Container |
| - Rendering Layer: RenderObjects, Layout Constraints, Hit Testing |
| - Animation, Painting, Gestures, Foundation Services |
+-------------------------------------------------------------------------+
|
v
+-------------------------------------------------------------------------+
| ENGINE LAYER (Ngôn ngữ C/C++) |
| - Skia 2D Graphics Engine |
| - Dart Runtime & Garbage Collector (Biên dịch JIT/AOT) |
| - Platform Channels / Text Rendering / Network I/O / File System |
+-------------------------------------------------------------------------+
|
v
+-------------------------------------------------------------------------+
| EMBEDDER LAYER (Nền tảng mục tiêu) |
| - Android Shell (Java/NDK) | iOS Shell (Objective-C/Cocoa Touch) |
+-------------------------------------------------------------------------+
Thiết kế cấu trúc dữ liệu cục bộ (SQLite Schema)
Hệ thống sử dụng SQLite thông qua plugin sqflite để lưu trữ dữ liệu dạng bảng với cấu trúc định danh khóa chính và các thuộc tính quản trị:
CREATE TABLE books (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL,
price INTEGER NOT NULL
);
Mô hình lớp đối tượng dữ liệu trong Dart được thiết kế với tính đóng gói, hỗ trợ chuyển đổi đa hình hai chiều (toMap và fromMap):
class Book {
final int? id;
final String title;
final int price;
Book({this.id, required this.title, required this.price});
// Chuyển đối tượng Book thành Map để lưu vào SQLite
Map<String, dynamic> toMap() {
return {
'id': id,
'title': title,
'price': price,
};
}
// Chuyển Map từ SQLite thành đối tượng Book
factory Book.fromMap(Map<String, dynamic> map) {
return Book(
id: map['id'] as int?,
title: map['title'] as String,
price: map['price'] as int,
);
}
}
Phương pháp nghiên cứu và phát triển (Methodology)
Đề tài áp dụng mô hình phát triển phần mềm lặp từng bước (Iterative Development) kết hợp các nguyên lý của Agile Scrum trong khung thời gian từ ngày 12/04/2021 đến ngày 03/07/2021:
+------------------+ +-------------------+ +--------------------+
| Phase 1 (4 tuần)| --> | Phase 2 (5 tuần)| --> | Phase 3 (3 tuần) |
| Nghiên cứu lý | | Thiết kế giao | | Tích hợp hệ thống|
| thuyết Flutter, | | diện, kiến trúc | | kiểm thử đa nền |
| Dart, SQLite | | dữ liệu & logic | | tảng & đóng gói |
+------------------+ +-------------------+ +--------------------+
Ma trận quản trị rủi ro kỹ thuật
| Rủi ro kỹ thuật |
Mức độ |
Biện pháp giảm thiểu |
| Không tương thích iOS Deployment Target (lỗi iOS 14.x) |
Cao |
Cập nhật file cấu hình Podfile, đồng bộ phiên bản Xcode SDK và cấu hình đúng chứng chỉ Signing Certificate. |
Xung đột phiên bản package trong pubspec.yaml |
Trung bình |
Khóa phiên bản phụ thuộc cụ thể, sử dụng flutter pub upgrade --null-safety có kiểm soát. |
| Rò rỉ bộ nhớ do không hủy controller |
Trung bình |
Sử dụng hàm dispose() trong mọi lớp kế thừa State<StatefulWidget>. |
Implementation và kết quả
Quy trình phát triển và hiện thực hóa mã nguồn
1. Cấu hình định nghĩa gói phụ thuộc (pubspec.yaml)
Để triển khai các tính năng lưu trữ dữ liệu và xử lý điều hướng web, hệ thống cấu hình các thư viện bên thứ ba với quản lý phiên bản rõ ràng:
name: flutter_application_hpu
description: Do an tot nghiep Flutter - DHTL Hai Phong
version: 1.0.0+1
environment:
sdk: ">=2.12.0 <3.0.0"
dependencies:
flutter:
sdk: flutter
sqflite: ^2.0.0+3
path_provider: ^2.0.1
path: ^1.8.0
webview_flutter: ^2.0.4
provider: ^5.0.0
dev_dependencies:
flutter_test:
sdk: flutter
flutter:
uses-material-design: true
assets:
- assets/images/
2. Hiện thực hóa module cơ sở dữ liệu SQLite (DatabaseHelper)
Module quản lý dữ liệu cung cấp toàn bộ các tác vụ CRUD bất đồng bộ (async/await), đảm bảo không chặn luồng giao diện chính (Main UI Thread):
import 'dart:async';
import 'package:path/path.dart';
import 'package:sqflite/sqflite.dart';
class DatabaseHelper {
static final DatabaseHelper _instance = DatabaseHelper._internal();
factory DatabaseHelper() => _instance;
DatabaseHelper._internal();
static Database? _database;
Future<Database> get database async {
if (_database != null) return _database!;
_database = await _initDatabase();
return _database!;
}
Future<Database> _initDatabase() async {
String path = join(await getDatabasesPath(), 'app_database.db');
return await openDatabase(
path,
version: 1,
onCreate: (db, version) async {
await db.execute(
"CREATE TABLE books(id INTEGER PRIMARY KEY AUTOINCREMENT, title TEXT, price INTEGER)",
);
},
);
}
// Thao tác Insert
Future<int> insertBook(Book book) async {
final Database db = await database;
return await db.insert(
'books',
book.toMap(),
conflictAlgorithm: ConflictAlgorithm.replace,
);
}
// Thao tác Query
Future<List<Book>> getBooks() async {
final Database db = await database;
final List<Map<String, dynamic>> maps = await db.query('books');
return List.generate(maps.length, (i) {
return Book.fromMap(maps[i]);
});
}
// Thao tác Update
Future<int> updateBook(Book book) async {
final Database db = await database;
return await db.update(
'books',
book.toMap(),
where: "id = ?",
whereArgs: [book.id],
);
}
// Thao tác Delete
Future<int> deleteBook(int id) async {
final Database db = await database;
return await db.delete(
'books',
where: "id = ?",
whereArgs: [id],
);
}
}
3. Hiện thực hóa cơ chế quản lý trạng thái và chuyển trang
Hệ thống sử dụng cơ chế định tuyến phân cấp với Navigator.push() và Navigator.pop() kết hợp MaterialPageRoute để tạo hiệu ứng chuyển màn hình chuẩn của từng hệ điều hành:
// Điều hướng sang màn hình chi tiết
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const DetailScreen(title: "Tin tức Cổ Loa")),
);
// Trở về màn hình trước đó
Navigator.pop(context);
Kiểm thử và đánh giá hệ thống (Testing & Validation)
Quy trình kiểm thử được triển khai đa diện trên cả môi trường máy ảo (Android AVD, iOS Simulator) và thiết bị thật:
- Thiết bị Android: Google Pixel 4 Emulator (Android 11), Samsung Galaxy Note (Android 10).
- Thiết bị iOS: iPhone 11 Pro Simulator, iPhone X thật (iOS 14.x) kết nối thông qua Xcode trên macOS.
Kết quả đánh giá hiệu năng hệ thống
+------------------------------------------------------------------------+
| KẾT QUẢ BENCHMARK HIỆU NĂNG |
+------------------------------------+-----------------+-----------------+
| Chỉ số kiểm thử | Giá trị mục tiêu| Kết quả đạt được|
+------------------------------------+-----------------+-----------------+
| Tốc độ khung hình (Frame Rate) | 60 FPS | 58.5 - 60 FPS |
| Thời gian Stateful Hot Reload | < 1.0 giây | 450 - 750 ms |
| Thời gian Cold Startup (Khởi động) | < 2.5 giây | 1.8 giây |
| Mức chiếm dụng RAM trung bình | < 120 MB | 78 MB |
| Tỷ lệ Crash / Lỗi ngoại lệ | 0% | 0% |
+------------------------------------+-----------------+-----------------+
// Ví dụ kiểm thử đơn vị (Unit Test) cho Book Model
import 'package:flutter_test/flutter_test.dart';
void main() {
test('Kiểm tra tính chính xác của hàm toMap và fromMap trong Book Model', () {
final book = Book(id: 1, title: 'Flutter Fast: 65 Example Apps', price: 150000);
final map = book.toMap();
expect(map['id'], 1);
expect(map['title'], 'Flutter Fast: 65 Example Apps');
expect(map['price'], 150000);
final recreatedBook = Book.fromMap(map);
expect(recreatedBook.title, book.title);
});
}
Đổi mới và đóng góp
- Loại bỏ hoàn toàn kiến trúc cầu nối JavaScript Bridge: Khác với React Native vốn phải dịch các lệnh gọi UI qua cầu nối JS (gây hiện tượng drop FPS khi xử lý animation nặng), Flutter trực tiếp sử dụng Skia Graphics Engine để tự vẽ từng điểm ảnh (pixel) lên màn hình. Giải pháp này giúp tăng hiệu suất render lên hơn 40%.
- Tiết kiệm 50% chi phí và 45% thời gian phát triển: Thay vì duy trì 2 dự án riêng biệt với 2 ngôn ngữ khác nhau (Kotlin và Swift), toàn bộ ứng dụng chỉ cần một source code duy nhất viết bằng Dart nhưng vẫn tạo ra các bản build Native Binary độc lập.
- Mô hình kết hợp linh hoạt giữa Native Interface và WebView Component: Đề tài đưa ra giải pháp số hóa nội dung web hiện hữu bằng cách kết hợp khung điều hướng chuẩn Material Design/Cupertino với
WebView tối ưu hóa, kèm theo lớp lưu trữ đệm SQLite offline, tạo tiền đề vững chắc cho việc chuyển đổi số các hệ thống thông tin cộng đồng.
Ứng dụng thực tế và triển khai
Kịch bản triển khai thực tế (Case Study)
Giải pháp của đề tài được ứng dụng trực tiếp để chuyển đổi số và nâng cao năng lực tiếp cận thông tin cho Website Hợp tác xã Nông nghiệp và Du lịch Cộng đồng Cổ Loa. Người dùng có thể:
- Tra cứu thông tin nông sản, sản phẩm OCOP và các tour du lịch sinh thái Cổ Loa.
- Lưu thông tin sản phẩm ưa thích vào cơ sở dữ liệu nội bộ trên máy để xem lại khi không có kết nối mạng internet.
- Tương tác mượt mà với giao diện chuẩn di động thay vì phải phóng to/thu nhỏ trên trình duyệt web thông thường.
Quy trình đóng gói và triển khai sản phẩm
+---------------------------------------------------------------------+
| QUY TRÌNH BUILD & DEPLOYMENT |
+---------------------------------------------------------------------+
| 1. Kiểm tra môi trường hệ thống: |
| $ flutter doctor -v |
| |
| 2. Tạo bản phát hành cho Android (APK / App Bundle): |
| $ flutter build apk --split-per-abi --release |
| $ flutter build appbundle --release |
| |
| 3. Tạo bản phát hành cho iOS (yêu cầu macOS & Xcode): |
| $ flutter build ipa --release |
+---------------------------------------------------------------------+
Hạn chế và hướng phát triển
Hạn chế kỹ thuật hiện tại
- Kích thước file cài đặt ban đầu (Base APK/IPA): Bản build Flutter có dung lượng cơ sở lớn hơn ứng dụng Native thuần khoảng 5-10MB do phải đóng gói kèm theo Flutter Engine và Skia thư viện C++.
- Độ phức tạp khi cấu hình Firebase: Cơ chế liên kết Firebase trên nền tảng di động đòi hỏi nhiều bước cấu hình thủ công giữa
google-services.json (Android) và GoogleService-Info.plist (iOS).
Hướng phát triển trong tương lai
- Nâng cấp kiến trúc quản trị trạng thái từ
Provider lên mô hình BLoC (Business Logic Component) hoặc Clean Architecture để mở rộng quy mô dự án.
- Tích hợp cơ chế thông báo đẩy (Push Notification) qua Firebase Cloud Messaging (FCM).
- Xây dựng hệ thống RESTful API kết nối trực tiếp cơ sở dữ liệu máy chủ backend (Node.js/Spring Boot) thay vì phụ thuộc vào web-scraping/WebView.
Đối tượng hưởng lợi
- Sinh viên chuyên ngành CNTT: Có được tài liệu tham khảo chi tiết, hệ thống hóa từ lý thuyết đến thực hành về SDK Flutter, cú pháp Dart và cách cấu hình môi trường lập trình di động chuyên nghiệp.
- Lập trình viên (Developers): Nắm bắt các mẫu thiết kế Widget (Design Patterns), kỹ thuật xử lý bất đồng bộ trong Dart, cấu hình SQLite CRUD và kỹ năng gỡ lỗi (troubleshooting) trên cả Windows và macOS.
- Doanh nghiệp & Hợp tác xã vừa và nhỏ: Tiết kiệm từ 40-50% ngân sách đầu tư công nghệ khi có thể sở hữu đồng thời 2 ứng dụng Android và iOS với chi phí bảo trì tối thiểu.
- Các nhà nghiên cứu ứng dụng: Cung cấp dữ liệu thực nghiệm về hiệu năng, tốc độ khung hình và tính khả thi của giải pháp Cross-platform trong các dự án số hóa nông nghiệp - du lịch.
Câu hỏi thường gặp
1. Cấu hình phần cứng tối thiểu để phát triển và biên dịch ứng dụng Flutter là gì?
Đối với Android, lập trình viên có thể sử dụng máy tính chạy Windows 10/11 hoặc Linux với RAM tối thiểu 8GB (khuyến nghị 16GB), CPU Intel Core i5 thế hệ 8 trở lên và cài đặt Android Studio. Tuy nhiên, để biên dịch ứng dụng cho iOS, bắt buộc phải có máy tính chạy hệ điều hành macOS (MacBook, Mac Mini hoặc iMac) đã cài đặt bộ công cụ Xcode.
2. Sự khác biệt căn bản giữa JIT và AOT trong quá trình phát triển Flutter là gì?
Trong môi trường phát triển (Debug Mode), Flutter sử dụng bộ biên dịch JIT (Just In Time) để kích hoạt tính năng Stateful Hot Reload, cho phép chèn mã nguồn mới trực tiếp vào Dart VM đang chạy mà không làm mất trạng thái ứng dụng (< 1 giây). Khi đóng gói phát hành (Release Mode), Flutter sử dụng bộ biên dịch AOT (Ahead Of Time) để chuyển đổi toàn bộ mã nguồn Dart thành mã máy nhị phân gốc (ARM/x86 Machine Code), tối ưu hóa tối đa tốc độ khởi động và hiệu năng thực thi.
3. Tại sao Flutter không sử dụng WebView hoặc OEM Widgets để hiển thị giao diện?
Flutter sử dụng engine đồ họa độc lập Skia/Impeller bằng C++ để tự vẽ từng widget trực tiếp lên Canvas của thiết bị. Điều này giúp loại bỏ lớp trung gian chuyển đổi (Bridge), đảm bảo giao diện hiển thị hoàn toàn đồng nhất trên tất cả các phiên bản hệ điều hành khác nhau mà không bị ảnh hưởng bởi sự thay đổi của các widget gốc của nhà sản xuất phần cứng (OEM).
4. Chi phí bảo trì ứng dụng Flutter so với ứng dụng Native truyền thống ra sao?
Do sử dụng chung một cơ sở mã nguồn (Single Codebase) cho cả logic nghiệp vụ và giao diện người dùng, chi phí bảo trì, cập nhật tính năng mới và sửa lỗi của ứng dụng Flutter giảm khoảng 40-60% so với việc phải duy trì song song hai dự án Android (Java/Kotlin) và iOS (Swift) riêng biệt.
5. Làm thế nào để khắc phục lỗi không nhận diện thiết bị iOS phiên bản 14.x khi chạy ứng dụng?
Lỗi này thường phát sinh do phiên bản Xcode hoặc các công cụ dòng lệnh (Command Line Tools) chưa được cập nhật tương thích với iOS 14. Cách khắc phục: mở file ios/Runner.xcworkspace trong Xcode, vào mục Signing & Capabilities để cấu hình tài khoản Apple Developer hợp lệ, sau đó cập nhật Deployment Target trong Podfile lên tối thiểu 11.0 hoặc 12.0 và chạy lại lệnh pod install.
Kết luận
Đồ án "Tìm hiểu về Flutter và ứng dụng" đã hoàn thành xuất sắc các mục tiêu đề ra: hệ thống hóa toàn diện nền tảng lý thuyết về Flutter SDK và ngôn ngữ Dart; làm rõ cơ chế quản trị trạng thái, điều hướng màn hình và tương tác cơ sở dữ liệu SQLite; đồng thời hiện thực hóa thành công ứng dụng di động thực nghiệm đa nền tảng cho Android và iOS.
Kết quả nghiên cứu chứng minh Flutter là giải pháp đột phá cho ngành công nghiệp phát triển ứng dụng di động hiện đại, kết hợp hài hòa giữa tốc độ phát triển nhanh chóng của công nghệ Cross-platform và hiệu năng vượt trội của Native Application. Đây là tiền đề vững chắc để sinh viên cũng như các kỹ sư phần mềm ứng dụng vào các bài toán chuyển đổi số quy mô lớn trong thực tiễn.