Hướng dẫn học Flutter cho người mới bắt đầu
Lộ trình học Flutter từ cơ bản đến nâng cao, bao gồm cài đặt môi trường và viết ứng dụng đầu tiên

Giới thiệu về Flutter
Flutter là một framework phát triển ứng dụng di động mã nguồn mở được phát triển bởi Google. Với Flutter, bạn có thể xây dựng ứng dụng di động chất lượng cao cho iOS và Android từ một codebase duy nhất. Không chỉ dừng lại ở ứng dụng di động, Flutter còn hỗ trợ phát triển ứng dụng cho Web, macOS, Windows và Linux.
Những ưu điểm nổi bật của Flutter:
- Cross-platform: Viết mã một lần và chạy trên nhiều nền tảng
- Hot Reload: Thay đổi code và thấy kết quả ngay lập tức
- UI đẹp và linh hoạt: Hỗ trợ tùy biến UI tới từng pixel
- Hiệu năng cao: Hiệu suất gần như tương đương với ứng dụng native
- Cộng đồng lớn mạnh: Nhiều package và plugin hỗ trợ
Lộ trình học Flutter từ cơ bản đến nâng cao
Giai đoạn 1: Nền tảng và thiết lập
1.1. Học Dart
Dart là ngôn ngữ lập trình được sử dụng trong Flutter. Trước khi bắt đầu với Flutter, bạn nên làm quen với Dart.
Các khái niệm cơ bản về Dart cần nắm:
var name = 'Nguyễn Văn A';
String city = 'Hà Nội';
final age = 25;
const PI = 3.14;
int add(int a, int b) {
return a + b;
}
int multiply(int a, int b) => a * b;
class Person {
String name;
int age;
Person(this.name, this.age);
void introduce() {
print('Xin chào, tôi là $name, $age tuổi.');
}
}
Tài nguyên học Dart:
1.2. Cài đặt Flutter SDK
Bước 1: Tải Flutter SDK
Truy cập trang tải xuống Flutter và tải xuống phiên bản phù hợp với hệ điều hành của bạn.
Bước 2: Giải nén file đã tải xuống
Giải nén file đã tải xuống vào thư mục bạn muốn cài đặt Flutter, ví dụ:
- Windows:
C:\dev\flutter
- macOS/Linux:
~/dev/flutter
Bước 3: Cập nhật biến môi trường PATH
Thêm thư mục flutter/bin
vào biến môi trường PATH:
-
Windows:
- Tìm kiếm "environment variables" trong menu Start
- Chọn "Edit the system environment variables"
- Nhấn "Environment Variables"
- Trong "System variables", chọn "Path" và click "Edit"
- Thêm đường dẫn đến thư mục
flutter\bin
- Nhấn "OK" để lưu
-
macOS/Linux:
- Mở file
~/.bashrc
, ~/.bash_profile
, hoặc ~/.zshrc
(tùy theo shell bạn đang sử dụng)
- Thêm dòng sau:
export PATH="$PATH:[đường dẫn đến thư mục flutter]/bin"
- Lưu file và chạy
source ~/.bashrc
(hoặc file tương ứng)
Bước 4: Kiểm tra cài đặt
Mở terminal hoặc command prompt và chạy lệnh:
Lệnh này sẽ kiểm tra cài đặt Flutter và báo cáo bất kỳ phụ thuộc nào còn thiếu. Hãy làm theo hướng dẫn để hoàn tất cài đặt.
1.3. Cài đặt IDE
Flutter làm việc tốt với nhiều IDE:
1.4. Tạo ứng dụng Flutter đầu tiên
Bằng dòng lệnh:
flutter create my_first_app
cd my_first_app
flutter run
Bằng IDE:
- Trong VS Code: Nhấn
Ctrl+Shift+P
(hoặc Cmd+Shift+P
trên macOS), chọn "Flutter: New Project"
- Trong Android Studio: Chọn "Start a new Flutter project"
Giai đoạn 2: Học các khái niệm cơ bản của Flutter
Flutter sử dụng Widgets để xây dựng giao diện người dùng. Tất cả trong Flutter đều là widgets, từ một nút bấm đơn giản đến cả ứng dụng.
Các loại widget cơ bản:
class MyStatelessWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
child: Text('Hello, Flutter!'),
);
}
}
class MyStatefulWidget extends StatefulWidget {
@override
_MyStatefulWidgetState createState() => _MyStatefulWidgetState();
}
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
return Column(
children: [
Text('Số lần nhấn: $_counter'),
ElevatedButton(
onPressed: _incrementCounter,
child: Text('Tăng'),
),
],
);
}
}
2.2. Layout trong Flutter
Hiểu cách sắp xếp và bố trí widgets là rất quan trọng trong Flutter.
Các widget layout phổ biến:
- Container: Widget đa năng để tùy chỉnh, tạo padding, margin, trang trí...
- Row và Column: Sắp xếp widget theo chiều ngang hoặc dọc
- Stack: Chồng các widget lên nhau
- Expanded và Flexible: Kiểm soát không gian mà widget chiếm trong Row hoặc Column
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Dòng 1'),
Text('Dòng 2'),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Icon(Icons.star),
Icon(Icons.star),
Icon(Icons.star),
],
),
],
);
}
2.3. State Management
Quản lý trạng thái (State Management) là một trong những khía cạnh quan trọng của Flutter.
Các phương pháp quản lý trạng thái:
- setState(): Phương pháp cơ bản cho các ứng dụng đơn giản
- Provider: Dễ học và được Flutter khuyên dùng
- Bloc/Cubit: Mạnh mẽ, phù hợp cho ứng dụng lớn
- GetX: All-in-one, đơn giản hóa nhiều tác vụ
- Riverpod: Cải tiến từ Provider
Ví dụ đơn giản với Provider:
class Counter {
int value = 0;
void increment() {
value++;
}
}
void main() {
runApp(
ChangeNotifierProvider(
create: (context) => Counter(),
child: MyApp(),
),
);
}
class CounterDisplay extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Text(
'${context.watch<Counter>().value}',
style: Theme.of(context).textTheme.headline4,
);
}
}
Giai đoạn 3: Xây dựng ứng dụng thực tế
3.1. Navigation và Routing
Điều hướng giữa các màn hình là phần cơ bản của hầu hết các ứng dụng.
Navigator.push(
context,
MaterialPageRoute(builder: (context) => SecondScreen()),
);
Navigator.pushNamed(context, '/second');
MaterialApp(
routes: {
'/': (context) => HomeScreen(),
'/second': (context) => SecondScreen(),
'/detail': (context) => DetailScreen(),
},
);
3.2. Networking và API
Hầu hết các ứng dụng cần giao tiếp với API.
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<List<Post>> fetchPosts() async {
final response = await http.get(Uri.parse('https://jsonplaceholder.typicode.com/posts'));
if (response.statusCode == 200) {
List<dynamic> body = jsonDecode(response.body);
return body.map((item) => Post.fromJson(item)).toList();
} else {
throw Exception('Failed to load posts');
}
}
class Post {
final int id;
final String title;
final String body;
Post({required this.id, required this.title, required this.body});
factory Post.fromJson(Map<String, dynamic> json) {
return Post(
id: json['id'],
title: json['title'],
body: json['body'],
);
}
}
3.3. Lưu trữ cục bộ
Flutter cung cấp nhiều cách để lưu trữ dữ liệu cục bộ.
import 'package:shared_preferences/shared_preferences.dart';
Future<void> saveData() async {
final prefs = await SharedPreferences.getInstance();
await prefs.setString('username', 'NguyenVanA');
await prefs.setInt('age', 25);
await prefs.setBool('isLoggedIn', true);
}
Future<void> readData() async {
final prefs = await SharedPreferences.getInstance();
final username = prefs.getString('username') ?? 'Guest';
final age = prefs.getInt('age') ?? 0;
final isLoggedIn = prefs.getBool('isLoggedIn') ?? false;
print('Username: $username, Age: $age, Logged in: $isLoggedIn');
}
Giai đoạn 4: Nâng cao kỹ năng
4.1. Animations
Animations làm cho ứng dụng trở nên sinh động và thú vị hơn.
AnimatedContainer(
duration: Duration(seconds: 1),
curve: Curves.fastOutSlowIn,
width: _expanded ? 200 : 100,
height: _expanded ? 100 : 50,
color: _expanded ? Colors.blue : Colors.red,
child: Center(child: Text('Nhấn vào tôi')),
);
class _MyAnimationState extends State<MyAnimation> with SingleTickerProviderStateMixin {
late AnimationController _controller;
late Animation<double> _animation;
@override
void initState() {
super.initState();
_controller = AnimationController(
duration: const Duration(seconds: 2),
vsync: this,
);
_animation = CurvedAnimation(
parent: _controller,
curve: Curves.easeInOut,
);
_controller.forward();
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return FadeTransition(
opacity: _animation,
child: const Text('Fade In Animation'),
);
}
}
4.2. Testing trong Flutter
Flutter hỗ trợ nhiều loại test:
- Unit tests: Kiểm tra logic không phụ thuộc vào UI
- Widget tests: Kiểm tra UI và tương tác
- Integration tests: Kiểm tra toàn bộ ứng dụng
void main() {
test('Counter value should be incremented', () {
final counter = Counter();
counter.increment();
expect(counter.value, 1);
});
}
void main() {
testWidgets('Counter increments smoke test', (WidgetTester tester) async {
await tester.pumpWidget(MyApp());
expect(find.text('0'), findsOneWidget);
await tester.tap(find.byIcon(Icons.add));
await tester.pump();
expect(find.text('1'), findsOneWidget);
});
}
4.3. CI/CD cho Flutter
Tích hợp liên tục và triển khai liên tục (CI/CD) giúp tự động hóa quy trình phát triển.
- Flutter CI/CD với GitHub Actions
- Fastlane cho iOS và Android
- Codemagic hoặc Bitrise cho Flutter
Giai đoạn 5: Tối ưu hóa và phát hành
Tối ưu hóa hiệu suất là quan trọng để ứng dụng chạy mượt mà.
- Sử dụng
const
constructor khi có thể
- Tránh rebuild không cần thiết
- Sử dụng Flutter DevTools để phân tích hiệu suất
const MyWidget(
key: Key('my_widget'),
child: Text('Hello'),
);
ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(items[index].title),
);
},
);
5.2. Phát hành ứng dụng
Phát hành ứng dụng lên App Store và Google Play Store.
App Store (iOS):
- Đăng ký Apple Developer Account
- Tạo App ID, Certificates, và Provisioning Profiles
- Đóng gói ứng dụng:
flutter build ipa
- Sử dụng Xcode để tải lên App Store Connect
Google Play Store (Android):
- Đăng ký Google Play Developer Account
- Tạo keystore cho ứng dụng
- Đóng gói ứng dụng:
flutter build appbundle
- Tải lên Google Play Console
Ứng dụng đầu tiên: Todo List App
Để áp dụng kiến thức đã học, hãy cùng xây dựng một ứng dụng Todo List đơn giản.
Bước 1: Tạo dự án mới
flutter create todo_app
cd todo_app
Bước 2: Định nghĩa model
class Todo {
final String id;
final String title;
bool isCompleted;
Todo({
required this.id,
required this.title,
this.isCompleted = false,
});
}
Bước 3: Tạo màn hình chính
import 'package:flutter/material.dart';
import 'package:todo_app/models/todo.dart';
class HomeScreen extends StatefulWidget {
@override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
final List<Todo> _todos = [];
final _textController = TextEditingController();
void _addTodo() {
if (_textController.text.isEmpty) return;
setState(() {
_todos.add(Todo(
id: DateTime.now().toString(),
title: _textController.text,
));
_textController.clear();
});
}
void _toggleTodo(String id) {
setState(() {
final todo = _todos.firstWhere((todo) => todo.id == id);
todo.isCompleted = !todo.isCompleted;
});
}
void _removeTodo(String id) {
setState(() {
_todos.removeWhere((todo) => todo.id == id);
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Todo App'),
),
body: Column(
children: [
Padding(
padding: const EdgeInsets.all(16.0),
child: Row(
children: [
Expanded(
child: TextField(
controller: _textController,
decoration: InputDecoration(
hintText: 'Thêm công việc mới...',
),
),
),
IconButton(
icon: Icon(Icons.add),
onPressed: _addTodo,
),
],
),
),
Expanded(
child: _todos.isEmpty
? Center(child: Text('Chưa có công việc nào!'))
: ListView.builder(
itemCount: _todos.length,
itemBuilder: (context, index) {
final todo = _todos[index];
return ListTile(
title: Text(
todo.title,
style: TextStyle(
decoration: todo.isCompleted
? TextDecoration.lineThrough
: null,
),
),
leading: Checkbox(
value: todo.isCompleted,
onChanged: (_) => _toggleTodo(todo.id),
),
trailing: IconButton(
icon: Icon(Icons.delete),
onPressed: () => _removeTodo(todo.id),
),
);
},
),
),
],
),
);
}
}
Bước 4: Cập nhật main.dart
import 'package:flutter/material.dart';
import 'package:todo_app/screens/home_screen.dart';
void main() {
runApp(TodoApp());
}
class TodoApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Todo App',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: HomeScreen(),
);
}
}
Bước 5: Chạy ứng dụng
Các tài nguyên học Flutter

Tài liệu chính thức
Khóa học trực tuyến
Cộng đồng và Diễn đàn
Packages và Libraries
- Pub.dev - Kho lưu trữ packages và plugins Flutter
Lời kết
Học Flutter có thể là một hành trình thú vị và bổ ích. Bằng cách theo dõi lộ trình này, bạn sẽ dần xây dựng được nền tảng vững chắc và phát triển các ứng dụng di động chất lượng cao. Hãy nhớ rằng, thực hành là chìa khóa để thành thạo Flutter - đừng ngại thử nghiệm và xây dựng các dự án thực tế.
Chúc bạn thành công trên con đường trở thành Flutter Developer!