Chào bạn, dưới đây là bộ 50 câu hỏi phỏng vấn Flutter từ cơ bản đến nâng cao, bao gồm giải thích chi tiết và code demo để bạn có thể ôn tập và chuẩn bị tốt nhất cho buổi phỏng vấn.
1. Flutter là gì? Tại sao nó lại sử dụng ngôn ngữ Dart?
Giải thích: Flutter là một UI SDK của Google để xây dựng ứng dụng biên dịch nguyên bản (native) cho di động, web và desktop từ một codebase duy nhất. Dart được chọn vì hỗ trợ cả JIT (Just-in-Time) để hot reload nhanh và AOT (Ahead-of-Time) để tối ưu hiệu suất khi release.
Code Demo: Không yêu cầu code phức tạp, chỉ cần cấu trúc main:
void main() => runApp(MyApp());
2. Sự khác biệt giữa StatelessWidget và StatefulWidget?
Giải thích:
StatelessWidgetkhông thay đổi trạng thái sau khi được dựng.StatefulWidgetcó thể thay đổi dữ liệu bên trong và cập nhật lại giao diện thông qua hàmsetState().Code Demo:
class MyText extends StatelessWidget {
@override
Widget build(BuildContext context) => Text("I am Stateless");
}
3. Hot Reload và Hot Restart khác nhau như thế nào?
Giải thích: Hot Reload đẩy các thay đổi code vào VM và cập nhật UI mà không mất State. Hot Restart khởi động lại toàn bộ app và làm mất State hiện tại.
Code Demo: (Cơ chế IDE)
4. Widget Tree, Element Tree và RenderObject Tree là gì?
Giải thích: - Widget Tree: Cấu trúc do cấu hình code.
Element Tree: Cầu nối giữa Widget và RenderObject, quản lý vòng đời.
RenderObject Tree: Trực tiếp vẽ giao diện lên màn hình.
Code Demo: (Cấu trúc hệ thống)
5. Vòng đời (Lifecycle) của một StatefulWidget?
Giải thích: Gồm các bước:
createState->initState->didChangeDependencies->build->didUpdateWidget->deactivate->dispose.Code Demo:
@override
void initState() {
super.initState();
print("Khởi tạo dữ liệu");
}
6. BuildContext là gì?
Giải thích: Context là một locator xác định vị trí của Widget trong Element Tree. Nó giúp truy cập các widget cha (như Theme, MediaQuery).
Code Demo:
Theme.of(context).primaryColor;
7. Sự khác biệt giữa main() và runApp()?
Giải thích:
main()là điểm bắt đầu của chương trình Dart.runApp()là hàm khởi chạy framework Flutter và gắn Widget gốc vào màn hình.Code Demo:
void main() {
runApp(MaterialApp(home: Text("Hello")));
}
8. SafeArea là gì?
Giải thích: Giúp Widget tránh các vùng "tai thỏ", thanh trạng thái hoặc các phần bị che khuất bởi phần cứng.
Code Demo:
SafeArea(child: Text("Nội dung an toàn"));
9. Expanded vs Flexible?
Giải thích: Cả hai đều dùng trong Row/Column.
Expandedbắt buộc chiếm hết không gian trống,Flexiblecó thể thu nhỏ lại nếu nội dung bên trong nhỏ hơn.Code Demo:
Row(children: [
Expanded(child: Container(color: Colors.red)),
Flexible(child: Container(color: Colors.blue)),
]);
10. Container vs SizedBox?
Giải thích:
SizedBoxdùng để cố định kích thước (nhẹ hơn).Containerhỗ trợ thêm decoration, padding, margin, transform (nặng hơn).Code Demo:
SizedBox(width: 20); // Tạo khoảng trống
Container(decoration: BoxDecoration(color: Colors.red));
11. Các loại Navigation trong Flutter?
Giải thích: Gồm Navigator 1.0 (Imperative - Push/Pop) và Navigator 2.0 (Declarative - Router API).
Code Demo:
Navigator.push(context, MaterialPageRoute(builder: (_) => DetailScreen()));
12. Ý nghĩa của từ khóa const trong Widget?
Giải thích: Giúp Flutter tái sử dụng Widget đó thay vì khởi tạo lại, từ đó tối ưu hiệu suất rebuild.
Code Demo:
const Text("Dữ liệu tĩnh");
13. Keys trong Flutter dùng để làm gì?
Giải thích: Giúp Flutter giữ đúng State khi các Widget cùng loại thay đổi vị trí trong Widget Tree (thường dùng trong danh sách có thể sắp xếp).
Code Demo:
ListTile(key: ValueKey(item.id));
14. Sự khác biệt giữa async, await và Future?
Giải thích:
Futurelà kết quả trả về trong tương lai.asyncđánh dấu hàm bất đồng bộ,awaitdừng việc thực hiện cho đến khi Future hoàn tất.Code Demo:
Future<void> fetchData() async {
var data = await api.get();
}
15. Stream là gì? Khác gì với Future?
Giải thích:
Futuretrả về 1 giá trị duy nhất rồi kết thúc.Streamlà một dòng dữ liệu trả về liên tục nhiều giá trị theo thời gian.Code Demo:
Stream<int> counter() async* {
yield 1; yield 2;
}
16. Provider là gì?
Giải thích: Là một thư viện quản lý trạng thái (State Management) dựa trên
InheritedWidget, giúp truyền dữ liệu từ cha xuống con dễ dàng.Code Demo:
Provider.of<MyModel>(context).doSomething();
17. BLoC (Business Logic Component) là gì?
Giải thích: Tách biệt Logic và UI bằng cách sử dụng Stream/Sink. UI gửi sự kiện (Event), BLoC xử lý và trả về trạng thái (State).
Code Demo: (Cần thư viện flutter_bloc)
context.read<CounterBloc>().add(Increment());
18. Mixins trong Dart là gì?
Giải thích: Là cách tái sử dụng code của một class trong nhiều hierarchy khác nhau mà không cần kế thừa (Inheritance). Dùng từ khóa
with.Code Demo:
mixin Logger { void log(String msg) => print(msg); }
class MyController with Logger {}
19. Sự khác biệt giữa double.infinity và MediaQuery.of(context).size.width?
Giải thích:
double.infinityyêu cầu Widget chiếm toàn bộ không gian mà cha nó cho phép.MediaQuerylấy chính xác kích thước vật lý của màn hình.
20. AppState vs EphemeralState?
Giải thích: EphemeralState là state cục bộ trong 1 widget (như index của PageView). AppState là state dùng chung cho toàn bộ app (như thông tin User).
21. Flutter Engine được viết bằng ngôn ngữ gì?
Giải thích: Chủ yếu bằng C++, thực hiện các nhiệm vụ đồ họa thông qua thư viện Skia (hoặc Impeller mới).
22. Tác dụng của pubspec.yaml?
Giải thích: Quản lý các dependency, phiên bản app, assets (hình ảnh, font) và các cấu hình môi trường.
23. Làm thế nào để gọi Native Code (Java/Swift) từ Flutter?
Giải thích: Sử dụng
MethodChannel.Code Demo:
static const platform = MethodChannel('com.example/battery');
final int result = await platform.invokeMethod('getBatteryLevel');
24. Các chế độ build: Debug, Profile, Release?
Giải thích: - Debug: Hỗ trợ Hot Reload, chậm.
Profile: Kiểm tra hiệu suất.
Release: Tối ưu kích thước, tốc độ nhanh nhất.
25. Tree Shaking là gì?
Giải thích: Quá trình loại bỏ các code không được sử dụng khi đóng gói ứng dụng (thường thấy khi xử lý icon font).
26. CustomPainter dùng để làm gì?
Giải thích: Dùng để vẽ các hình dạng đồ họa phức tạp (đường thẳng, hình tròn, path) mà các widget cơ bản không đáp ứng được.
27. Stack vs Column?
Giải thích:
Columnxếp chồng các widget theo chiều dọc (không đè lên nhau).Stackcho phép các widget nằm đè lên nhau.
28. Ý nghĩa của InkWell và GestureDetector?
Giải thích: Cả hai bắt sự kiện chạm.
InkWellcó hiệu ứng ripple (gợn sóng),GestureDetectorthì không nhưng hỗ trợ nhiều cử chỉ hơn (kéo, thả, xoay).
29. Làm thế nào để xử lý lỗi trong Future?
Giải thích: Dùng
try-catchhoặc.catchError().Code Demo:
fetchData().catchError((e) => print(e));
30. Sự khác biệt giữa Final và Const?
Giải thích:
Constlà hằng số lúc biên dịch (compile-time).Finallà hằng số lúc chạy (runtime) - chỉ gán giá trị được một lần.
31. HTTP Request trong Flutter?
Giải thích: Thường dùng package
httphoặcdio.Code Demo:
var response = await http.get(Uri.parse('url'));
32. FutureBuilder vs StreamBuilder?
Giải thích:
FutureBuilderlắng nghe 1 Future duy nhất.StreamBuilderlắng nghe 1 Stream và cập nhật UI mỗi khi có dữ liệu mới đổ về.
33. Làm sao để ẩn Debug Banner?
Giải thích: Set
debugShowCheckedModeBanner: falsetrongMaterialApp.
34. AspectRatio widget dùng làm gì?
Giải thích: Cố định tỷ lệ khung hình (ví dụ 16:9) cho widget con bên trong.
35. Các loại Button trong Flutter?
Giải thích: ElevatedButton, OutlinedButton, TextButton, IconButton.
36. Lớp InheritedWidget là gì?
Giải thích: Là lớp cơ sở cho phép truyền dữ liệu xuống sâu trong cây Widget mà không cần truyền qua constructor của từng lớp trung gian.
37. Listview.builder() có lợi ích gì?
Giải thích: Chỉ khởi tạo những item đang hiển thị trên màn hình, giúp tiết kiệm bộ nhớ cho danh sách dài.
38. Làm thế nào để lưu dữ liệu cục bộ?
Giải thích: Dùng
shared_preferences(key-value đơn giản) hoặcsqflite(database),Hive(NoSQL).
39. SchedulerBinding là gì?
Giải thích: Dùng để chạy một task sau khi frame hiện tại đã được vẽ xong (thường dùng để hiển thị Dialog ngay sau khi vào màn hình).
Code Demo:
SchedulerBinding.instance.addPostFrameCallback((_) => showMyDialog());
40. Widget Opacity vs Visibility vs Offstage?
Giải thích: -
Opacity: Làm mờ nhưng vẫn chiếm chỗ.Visibility: Có thể ẩn hoàn toàn và không chiếm chỗ.Offstage: Vẫn tồn tại nhưng không được vẽ và không chiếm chỗ.
41. Null Safety trong Dart?
Giải thích: Ngăn chặn lỗi "null pointer exception" bằng cách phân biệt rõ kiểu dữ liệu có thể null (
int?) và không thể null (int).
42. Late keyword dùng khi nào?
Giải thích: Khai báo một biến sẽ được khởi tạo sau nhưng đảm bảo nó không null khi sử dụng.
43. Extension methods là gì?
Giải thích: Cho phép thêm chức năng mới vào các class có sẵn mà không cần kế thừa.
Code Demo:
extension StringExt on String {
bool get isEmail => contains('@');
}
44. Isolates là gì?
Giải thích: Dart chạy đơn luồng (Single-thread).
Isolateslà cách chạy các tác vụ nặng trên một luồng riêng biệt để không làm lag UI.
45. Tại sao nói Flutter có hiệu năng 60fps?
Giải thích: Nhờ Engine Skia tự vẽ mọi pixel, không qua cầu nối (bridge) trung gian như React Native.
46. shrinkWrap: true trong ListView là gì?
Giải thích: Buộc ListView chỉ chiếm không gian vừa đủ với các item bên trong, thay vì cố gắng chiếm toàn bộ không gian của cha.
47. GlobalKey dùng khi nào?
Giải thích: Truy cập trực tiếp vào State của một widget khác hoặc giữ State khi widget di chuyển giữa các cha khác nhau.
48. Làm thế nào để thay đổi hướng màn hình (Portrait/Landscape)?
Giải thích: Sử dụng
SystemChrome.setPreferredOrientations.
49. Flutter Flavor là gì?
Giải thích: Cấu hình các môi trường khác nhau (Dev, Staging, Prod) với các bundle ID và cấu hình API khác nhau.
50. Sự khác biệt giữa map và list trong Dart?
Giải thích:
Listlà danh sách có thứ tự.Maplà tập hợp các cặp key-value (mỗi key là duy nhất).