PRM393Chưa đoKỳ 8Chuyên ngành Cập nhật 07/09/2026

Lập trình di động (Flutter) - Mobile Programming

Lập trình di động với Flutter là môn học xây dựng ứng dụng đa nền tảng Android và iOS bằng Flutter và ngôn ngữ Dart. Ngân hàng câu hỏi trắc nghiệm PRM393 có giải thích bao quát trọn bộ chương trình: cài đặt Flutter SDK, cấu trúc project, hot reload và DevTools, nền tảng Dart (kiểu dữ liệu, null safety, class, collection, Map, generics, mixin, package và import), lập trình bất đồng bộ với Future, async/await, Stream, StreamController và StreamBuilder, dựng giao diện bằng widget tree, Scaffold, ListView, ThemeData, bố cục Row/Column, GridView, Stack, LayoutBuilder, MediaQuery và responsive UI, điều hướng với Navigator 1.0/2.0, named route, deep link và guarded route, form với TextEditingController và validation, gọi REST API bằng http, parse JSON, FutureBuilder, phân trang và caching, lưu trữ cục bộ bằng SharedPreferences, SQLite (sqflite) và Hive, xác thực bằng token và refresh token, quản lý state với setState, Provider, BLoC và Cubit, animation với Tween cùng AnimatedSwitcher, tối ưu hiệu năng bằng RepaintBoundary và thu hẹp phạm vi rebuild, kiểm thử unit/widget/integration, quản lý mã nguồn bằng Git và build - release ứng dụng. Tài liệu ôn thi FE dành cho sinh viên FPT University.

512Câu hỏi
1Bộ đề
15Chủ đề
5,02 đánh giá

Câu hỏi của môn

424/512 câuCòn 88
AIt provides a default value if the expression on its left is null.
BIt forcefully asserts that a nullable expression is non-null.
CIt contains the source code for unit, widget, and integration tests.
DIt manages the platform-specific transition animation between screens.
Lời giải
Trong một dự án Flutter, mục đích của thư mục `test/` là chứa mã nguồn cho các bài kiểm tra đơn vị, widget và tích hợp. Các bài kiểm tra này giúp đảm bảo rằng mã nguồn của dự án hoạt động đúng như mong đợi. Thư mục `test/` thường được sử dụng để kiểm tra các chức năng của ứng dụng, chẳng hạn như việc nhập dữ liệu, giao diện người dùng và các tính năng khác. Việc viết các bài kiểm tra này giúp phát hiện ra các lỗi và vấn đề trong mã nguồn sớm, từ đó giúp cải thiện chất lượng của dự án. Ngoài ra, các bài kiểm tra cũng giúp đảm bảo rằng mã nguồn của dự án tuân thủ các quy tắc và tiêu chuẩn của dự án.
Mở trang câu hỏi này →
AIt helps Flutter's framework uniquely identify widgets to preserve state during list modifications.
BUnit tests validate pure logic, while widget tests validate UI rendering and interaction.
CIt ensures the UI avoids system intrusions like notches, status bars, and camera cutouts.
DIt prevents unnecessary rebuilds of widgets that do not change during the app's lifecycle.
Lời giải
Trong Flutter, `ValueKey` đóng vai trò quan trọng trong việc tối ưu hóa `ListView`. Khi bạn sử dụng `ValueKey`, Flutter có thể duy trì trạng thái của từng widget trong danh sách ngay cả khi danh sách được thay đổi. Điều này giúp ngăn chặn việc rebuild widget không cần thiết và cải thiện hiệu suất của ứng dụng. Tính năng này đặc biệt hữu ích khi bạn cần hiển thị một danh sách lớn các widget và muốn đảm bảo rằng trạng thái của từng widget được duy trì chính xác.
Mở trang câu hỏi này →
AMany similar widgets — `find.byKey` is more stable than text
BReplaces `expect`
CWeb only
DNever
Lời giải
Một khóa (key) trên một widget hữu ích trong các bài kiểm tra khi có nhiều widget tương tự. Trong trường hợp này, việc sử dụng khóa để tìm kiếm widget là ổn định hơn so với việc sử dụng văn bản. Điều này là vì khóa thường duy nhất và không thay đổi trong suốt quá trình chạy thử nghiệm, trong khi văn bản có thể thay đổi tùy thuộc vào nội dung của widget. Vì vậy, việc sử dụng khóa để tìm kiếm widget giúp đảm bảo rằng các bài kiểm tra luôn tìm thấy widget mong muốn, ngay cả khi nội dung của widget thay đổi. Điều này giúp tăng độ tin cậy và ổn định của các bài kiểm tra.
Mở trang câu hỏi này →
Atester.pumpAndSettle()
Btester.enterText()
CListView.builder
DNavigator.pushNamed
Lời giải
Để chuyển đến một màn hình mới bằng cách truyền tên của một tuyến đường cụ thể, bạn cần sử dụng phương thức Navigator.pushNamed(). Phương thức này cho phép bạn chuyển đến một màn hình mới bằng cách sử dụng tên của tuyến đường mà bạn đã định nghĩa trong tệp routes của ứng dụng. Điều này giúp bạn có thể dễ dàng quản lý và chuyển đổi giữa các màn hình trong ứng dụng của mình. Ví dụ, nếu bạn muốn chuyển đến màn hình Chi tiết sản phẩm, bạn có thể sử dụng phương thức Navigator.pushNamed('ProductDetail') để thực hiện việc này.
Mở trang câu hỏi này →
AUnit tests don’t run on dev machines
BIntegration is faster
CFlutter forbids integration
DUnit/widget are fast and stable; integration is slow and flaky — keep few critical E2E flows
Lời giải
Pyramida kiểm tra ủng hộ nhiều đơn vị kiểm tra hơn tích hợp vì lý do đơn vị kiểm tra nhanh và ổn định, trong khi tích hợp chậm và không chắc chắn. Điều này có nghĩa là bạn nên có nhiều đơn vị kiểm tra hơn để đảm bảo rằng từng phần của ứng dụng hoạt động chính xác. Tuy nhiên, bạn không cần phải kiểm tra tất cả các trường hợp, chỉ cần tập trung vào các trường hợp quan trọng. Điều này giúp giảm thiểu thời gian và công sức cần thiết để chạy các thử nghiệm.
Mở trang câu hỏi này →
ATrue
BFalse
Lời giải
Khi xây dựng ứng dụng Flutter, việc kiểm soát kích thước của ứng dụng là rất quan trọng để đảm bảo hiệu suất và trải nghiệm người dùng tốt hơn. Command 'flutter build apk --analyze-size' được sử dụng để phân tích và đánh giá các thành phần nào đóng góp nhiều nhất vào kích thước của ứng dụng. Điều này giúp nhà phát triển có thể xác định và tối ưu hóa các thành phần không cần thiết hoặc có thể được giảm kích thước để giảm kích thước tổng thể của ứng dụng. Việc sử dụng command này cũng giúp nhà phát triển có thể tối ưu hóa quy trình xây dựng và phân phối ứng dụng của mình.
Mở trang câu hỏi này →
ATrue
BFalse
Lời giải
Chế độ Profile Mode được sử dụng để kiểm tra các tính năng hiệu suất của ứng dụng như FPS và jank trước khi triển khai. Điều này cho phép các nhà phát triển đánh giá và cải thiện hiệu suất của ứng dụng mà không cần phải triển khai nó. Chế độ Profile Mode thường được sử dụng trong quá trình phát triển và thử nghiệm để đảm bảo rằng ứng dụng hoạt động mượt mà và không có sự gián đoạn. Nó cũng giúp các nhà phát triển xác định và giải quyết các vấn đề hiệu suất trước khi ứng dụng được phát hành.
Mở trang câu hỏi này →
ALong lists — builder only builds items in the viewport (lazy)
BAlways same performance
CBuilder never works
DEven for 1000 items always use `children`
Lời giải
Khi sử dụng ListView trong Flutter, bạn có thể chọn giữa hai cách khác nhau để tạo danh sách: sử dụng thuộc tính children hoặc ListView.builder. Trong trường hợp sử dụng children, bạn cần tạo tất cả các item trong danh sách trước khi hiển thị. Điều này có thể dẫn đến việc sử dụng nhiều tài nguyên và giảm hiệu suất, đặc biệt khi danh sách rất dài. Ngược lại, ListView.builder cho phép bạn tạo các item chỉ khi chúng được hiển thị trong viewport. Điều này giúp tiết kiệm tài nguyên và cải thiện hiệu suất. Vì vậy, ListView.builder là lựa chọn tốt hơn khi bạn cần hiển thị danh sách dài.
Mở trang câu hỏi này →
AiOS only
BSame
CBoth entered by users on Play
D`versionCode` integer bumps each upload; `versionName` user-visible string
Lời giải
Trong phát triển ứng dụng Android, `versionCode` và `versionName` là hai thuộc tính quan trọng trong tệp AndroidManifest.xml. `versionCode` là một số nguyên tăng dần sau mỗi lần cập nhật ứng dụng, giúp hệ thống quản lý phiên bản (version management) xác định phiên bản ứng dụng hiện tại. `versionName`, mặt khác, là một chuỗi ký tự được sử dụng để hiển thị phiên bản ứng dụng cho người dùng. Điều này có nghĩa là `versionCode` được tự động tăng lên sau mỗi lần cập nhật, trong khi `versionName` có thể được cập nhật theo ý muốn của nhà phát triển để hiển thị cho người dùng. Ví dụ, phiên bản ứng dụng có thể là 1.2, nhưng `versionCode` có thể là 5, nếu đã có 4 lần cập nhật trước đó.
Mở trang câu hỏi này →
ATrue
BFalse
Lời giải
Một 'Release Build' thực sự không bao gồm tất cả thông tin debug để giúp khắc phục các vấn đề trên thiết bị vật lý. Thay vào đó, nó được thiết kế để chạy trên các thiết bị sản xuất và thường được sử dụng để phân phối phần mềm cho người dùng cuối. Thông tin debug có thể làm tăng kích thước của file executable và có thể chứa thông tin nhạy cảm về mã nguồn, vì vậy nó thường được loại bỏ trong quá trình xây dựng release. Điều này giúp đảm bảo rằng phần mềm được phân phối là ổn định và an toàn để sử dụng.
Mở trang câu hỏi này →
APlay prefers/requires AAB for splits/optimization; APK often for sideload/internal
BSame
CAAB is iOS-only
DAPK cannot install
Lời giải
AAB (Android App Bundle) và APK (file cài đặt Android) là hai định dạng khác nhau của ứng dụng Android. Khi phân phối ứng dụng trên Google Play, AAB được ưu tiên vì nó cho phép Google Play Store phân phối ứng dụng theo các phiên bản khác nhau dựa trên thiết bị và hệ điều hành của người dùng. Điều này giúp tối ưu hóa kích thước ứng dụng và giảm thiểu thời gian tải xuống. Tuy nhiên, trong một số trường hợp, APK vẫn được sử dụng, chẳng hạn như khi người dùng muốn cài đặt ứng dụng từ nguồn bên ngoài hoặc khi cần cài đặt ứng dụng trên thiết bị không có kết nối Internet.
Mở trang câu hỏi này →
ATrue
BFalse
Lời giải
Một AppBundle (.aab) là định dạng được khuyến nghị để xuất bản ứng dụng Flutter lên Google Play. Khi xuất bản ứng dụng Flutter lên Google Play, bạn cần tạo một tệp tin AppBundle (.aab) thay vì tệp tin APK (.apk). Định dạng AppBundle (.aab) cung cấp nhiều lợi ích, bao gồm khả năng phân phối ứng dụng lên Google Play Store một cách dễ dàng hơn và khả năng cập nhật ứng dụng một cách tự động. Ngoài ra, định dạng AppBundle (.aab) cũng giúp giảm thiểu kích thước tệp tin ứng dụng và tăng tốc độ tải xuống. Vì vậy, nếu bạn muốn xuất bản ứng dụng Flutter lên Google Play, bạn nên sử dụng định dạng AppBundle (.aab).
Mở trang câu hỏi này →
417build(BuildContext context) returns?4 lựa chọn
AFunction
BState
CWidget
DTheme
Lời giải
Khi xây dựng một ứng dụng Flutter, bạn sẽ thường xuyên gặp hàm build(BuildContext context). Hàm này có nhiệm vụ tạo ra một widget mới dựa trên trạng thái của ứng dụng. Widget là một phần tử cơ bản trong giao diện người dùng của ứng dụng Flutter. Nó có thể là một text, một hình ảnh, một button, hoặc bất kỳ thứ gì khác. Hàm build(BuildContext context) sẽ trả về một widget mới, và widget này sẽ được thêm vào cây widget của ứng dụng. Điều này sẽ giúp ứng dụng của bạn được cập nhật theo thời gian và phản ứng với các sự kiện của người dùng.
Mở trang câu hỏi này →
Aflutter build apk --release --analyze-size
Bflutter clean
Cflutter pub get --analyze
Ddart fix --apply
Lời giải
Để phân tích kích thước của bản phát hành (release build size), bạn cần sử dụng lệnh phù hợp. Trong các lựa chọn trên, lệnh "flutter build apk --release --analyze-size" là lựa chọn đúng. Lệnh này cho phép bạn phân tích kích thước của bản phát hành APK mà không cần phải xây dựng nó. Điều này giúp bạn có thể dự đoán kích thước của ứng dụng trên thiết bị di động trước khi xây dựng nó. Ngoài ra, lệnh này cũng cho phép bạn phân tích kích thước của các tệp tin và thư viện được sử dụng trong ứng dụng của bạn. Điều này giúp bạn có thể tối ưu hóa kích thước của ứng dụng và giảm thiểu thời gian tải xuống.
Mở trang câu hỏi này →
ATrue
BFalse
Lời giải
Khi bạn tách một mục danh sách phức tạp thành một widget riêng biệt, hiệu suất có thể được cải thiện bằng cách giảm thiểu các rebuild không cần thiết. Điều này xảy ra vì widget riêng biệt không phải rebuild lại khi danh sách phức tạp thay đổi. Ví dụ, nếu bạn có một danh sách phức tạp với nhiều mục và bạn muốn thêm hoặc xóa một mục, widget riêng biệt sẽ không bị ảnh hưởng bởi sự thay đổi này. Điều này giúp giảm thiểu thời gian rebuild và cải thiện hiệu suất tổng thể của ứng dụng.
Mở trang câu hỏi này →
APerformance Timeline in DevTools
Bflutter build apk --analyze-size
Cfactory Model.fromJson(Map<String, dynamic> json)
DString interpolation using `${expression}`
Lời giải

Trong Dart, để chèn giá trị của một biểu thức vào một chuỗi, chúng ta sử dụng cú pháp chèn chuỗi (string interpolation). Cú pháp này sử dụng dấu ngoặc nhọn `${expression}` để chèn giá trị của biểu thức vào chuỗi. Ví dụ:

Lời giải
var name = 'Dart';
print('Xin chào, tôi là $name');

Trong ví dụ trên, giá trị của biến `name` được chèn vào chuỗi 'Xin chào, tôi là ${name}'. Điều này giúp chúng ta tạo ra các chuỗi phức tạp và dễ đọc hơn.

Mở trang câu hỏi này →
Aflutter build apk --analyze-size
BAn authentication token.
CArrange, Act, and Assert.
DPerformance Timeline in DevTools
Lời giải
Trong Lab 11, mẫu 'AAA' được sử dụng để kiểm tra các chức năng của ứng dụng. Mỗi chữ cái trong 'AAA' đại diện cho một bước trong quá trình kiểm tra. 'A' là Arrange, bước này liên quan đến việc chuẩn bị dữ liệu và trạng thái ban đầu của ứng dụng. 'A' thứ hai là Act, bước này liên quan đến việc thực hiện hành động hoặc chức năng cần kiểm tra. 'A' thứ ba là Assert, bước này liên quan đến việc xác minh kết quả sau khi thực hiện hành động hoặc chức năng. Mẫu 'AAA' giúp các nhà phát triển tổ chức và thực hiện các thử nghiệm hiệu quả hơn.
Mở trang câu hỏi này →
ATrue
BFalse
Lời giải
Khi xây dựng danh sách dài, ListView.builder được coi là lựa chọn hiệu quả hơn so với ListView thông thường. Điều này là vì ListView.builder được thiết kế để xây dựng danh sách một cách động, nghĩa là nó chỉ tạo ra các yếu tố cần thiết trong danh sách khi chúng được hiển thị trên màn hình. Điều này giúp giảm thiểu việc tạo ra các yếu tố không cần thiết và cải thiện hiệu suất của ứng dụng. Trong khi đó, ListView thông thường sẽ tạo ra tất cả các yếu tố trong danh sách ngay từ đầu, ngay cả khi chúng không được hiển thị trên màn hình. Điều này có thể dẫn đến lãng phí tài nguyên và giảm hiệu suất của ứng dụng.
Mở trang câu hỏi này →
ATrue
BFalse
Lời giải
Công cụ 'Widget Inspector' trong DevTools cho phép các nhà phát triển visual hóa cây widget và các ràng buộc bố cục. Công cụ này giúp các nhà phát triển hiểu rõ hơn về cách widget được sắp xếp và bố trí trên màn hình. Nó cho phép họ xem xét và chỉnh sửa các ràng buộc bố cục, từ đó giúp cải thiện hiệu suất và tính thẩm mỹ của ứng dụng. Việc sử dụng công cụ này cũng giúp các nhà phát triển xác định và giải quyết các vấn đề liên quan đến bố cục và widget.
Mở trang câu hỏi này →
ANo effect
BRequired for performance
CBest optimization
DFlutter treats every item as new — loses scroll/selection state
Lời giải
Khi sử dụng `UniqueKey()` cho mỗi item trong `ListView.builder` trong quá trình `build`, mục đích chính là để giúp Flutter xác định từng item là duy nhất. Điều này đặc biệt quan trọng khi bạn muốn giữ nguyên trạng thái cuộn và chọn lựa của người dùng sau khi item được xây dựng lại. Nếu không sử dụng `UniqueKey()`, Flutter sẽ coi mỗi item là mới và sẽ mất trạng thái cuộn và chọn lựa hiện tại. Vì vậy, việc sử dụng `UniqueKey()` là cần thiết để đảm bảo rằng trạng thái của người dùng không bị mất khi item được xây dựng lại.
Mở trang câu hỏi này →