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

324/512 câuCòn 188
305How does `Wrap` differ from `Row`?4 lựa chọnDễ100% trả lời đúng
ASame
B`Row` wraps lines automatically
C`Wrap` wraps to the next line when out of space; `Row` may overflow
D`Wrap` cannot hold `Chip`
Lời giải
Wrap và Row là hai loại widget trong Flutter. Mặc dù cả hai đều có thể chứa nhiều widget con, nhưng chúng có cách xử lý kích thước khác nhau. Row sẽ tự động.wrap dòng khi cần thiết, trong khi Wrap sẽ.wrap widget con sang dòng tiếp theo khi không còn đủ không gian. Điều này có nghĩa là Row có thể gây ra tình trạng tràn màn hình nếu widget con quá lớn, trong khi Wrap sẽ đảm bảo rằng tất cả widget con đều được hiển thị mà không gây ra tràn màn hình. Vì vậy, Wrap phù hợp hơn khi bạn cần đảm bảo rằng widget con của mình sẽ được hiển thị một cách hợp lý trên màn hình.
Mở trang câu hỏi này →
AAlways one column
BiPad only
CMore/fewer columns based on screen width
DDisable scrolling
Lời giải
GridView.count được sử dụng để tạo một lưới có thể điều chỉnh kích thước dựa trên chiều rộng màn hình. Khi sử dụng crossAxisCount từ MediaQuery.width, GridView sẽ tự động điều chỉnh số cột dựa trên chiều rộng màn hình. Điều này giúp tạo ra một giao diện người dùng linh hoạt và phù hợp với nhiều loại thiết bị khác nhau. Ví dụ, trên màn hình rộng, GridView có thể hiển thị nhiều cột hơn, trong khi trên màn hình nhỏ, nó có thể hiển thị ít cột hơn. Điều này giúp tối ưu hóa không gian và tạo ra một trải nghiệm người dùng tốt hơn.
Mở trang câu hỏi này →
307What does `OrientationBuilder` provide?4 lựa chọn
ABattery only
BColors only
CPortrait vs landscape to switch layout
DUnrelated to layout
Lời giải
OrientationBuilder là một lớp xây dựng trong Android, giúp chúng ta điều chỉnh layout dựa trên hướng của thiết bị. Nó cho phép chúng ta chuyển đổi layout khi thiết bị được xoay từ ngang sang dọc hoặc ngược lại. Điều này giúp ứng dụng của chúng ta có thể thích nghi với nhiều kích thước màn hình và hướng khác nhau. OrientationBuilder cung cấp một số phương thức để chúng ta có thể điều chỉnh layout, chẳng hạn như việc chuyển đổi layout khi thiết bị được xoay.
Mở trang câu hỏi này →
308What is 'autovalidation' in the context of Flutter forms?4 lựa chọnTrung bình67% trả lời đúng
AIt is called exactly once when the widget is inserted into the tree, used for one-time initialisation.
BMediaQuery provides device screen dimensions, while LayoutBuilder provides the constraints of the parent widget.
CA feature that automatically triggers validation logic without waiting for a manual submit button press.
DIt creates a Future that completes after a specified duration, often used to simulate network latency.
Lời giải
Tính năng tự động xác thực (autovalidation) trong Flutter là một tính năng quan trọng khi xây dựng các form. Nó cho phép tự động kích hoạt logic xác thực mà không cần chờ đợi nút submit được nhấn. Điều này giúp người dùng có trải nghiệm tốt hơn khi nhập dữ liệu vào form. Khi sử dụng autovalidation, Flutter sẽ tự động kiểm tra các trường nhập liệu và thông báo lỗi nếu có. Điều này giúp người dùng dễ dàng nhận biết và sửa lỗi, từ đó tăng hiệu suất và giảm thiểu thời gian chờ đợi. Ngoài ra, tính năng này cũng giúp giảm thiểu số lượng lỗi nhập liệu và tăng cường bảo mật cho ứng dụng.
Mở trang câu hỏi này →
AIt prevents unnecessary rebuilds of widgets that do not change during the app's lifecycle.
BIt allows a single codebase to render UI using its own engine across different platforms.
CIt uniquely identifies the Form and allows access to its state for validation and saving.
DIt ensures the UI avoids system intrusions like notches, status bars, and camera cutouts.
Lời giải
Widget SafeArea được sử dụng để đảm bảo giao diện người dùng (UI) tránh các khu vực hệ thống như notch, thanh trạng thái và camera cutout. Điều này giúp đảm bảo rằng UI luôn được hiển thị một cách đầy đủ và không bị ảnh hưởng bởi các tính năng hệ thống. Khi sử dụng SafeArea, bạn có thể yên tâm rằng UI của mình sẽ luôn được hiển thị một cách chính xác và đầy đủ, ngay cả khi ứng dụng được chạy trên các thiết bị có notch hoặc camera cutout.
Mở trang câu hỏi này →
310When does `MediaQuery.viewInsets.bottom` increase?4 lựa chọnDễ100% trả lời đúng
AWhen the soft keyboard covers the bottom — used to push UI
BNever changes
COn rotation
DWhen enabling dark mode
Lời giải
Khi bạn muốn biết khi nào giá trị `MediaQuery.viewInsets.bottom` sẽ tăng lên, hãy hiểu rằng đây là một thuộc tính được sử dụng để xác định khoảng trống ở dưới cùng của màn hình. Giá trị này sẽ tăng lên khi bàn phím ảo mềm (soft keyboard) che phủ phần dưới cùng của màn hình. Điều này thường xảy ra khi bạn nhập văn bản vào một trường văn bản (text field) trên màn hình. Khi bàn phím ảo mềm xuất hiện, nó sẽ đẩy phần dưới cùng của màn hình lên, khiến giá trị `MediaQuery.viewInsets.bottom` tăng lên. Điều này cho phép các ứng dụng điều chỉnh bố cục của mình để tránh bị che khuất bởi bàn phím ảo mềm.
Mở trang câu hỏi này →
311When prefer `LayoutBuilder` over `MediaQuery.sizeOf` in a tight area?4 lựa chọnDễ100% trả lời đúng
AWhen you need **parent** constraints (card, dialog), not full screen
BOnly with `GridView`
CNever
DWhen writing tests
Lời giải
Khi nào nên ưu tiên sử dụng `LayoutBuilder` so với `MediaQuery.sizeOf` trong một khu vực chật hẹp? Đó là khi bạn cần đặt các ràng buộc cho **phụ cha** (parent) của widget, chẳng hạn như card hoặc dialog, thay vì toàn bộ màn hình. `LayoutBuilder` cho phép bạn đặt các ràng buộc cho widget con dựa trên kích thước của widget cha, giúp bạn có thể tạo ra các layout phức tạp và linh hoạt hơn. Ví dụ, bạn có thể sử dụng `LayoutBuilder` để tạo ra một card có kích thước tùy chỉnh dựa trên kích thước của màn hình, hoặc để tạo ra một dialog có kích thước phù hợp với nội dung của nó.
Mở trang câu hỏi này →
ATrue
BFalse
Lời giải
FocusNode được sử dụng để di chuyển con trỏ từ một trường văn bản sang trường văn bản khác một cách lập trình.
Mở trang câu hỏi này →
ATrue
BFalse
Lời giải
Mẹo để ẩn bàn phím trên thiết bị di động trong Flutter là sử dụng phương thức FocusScope.of(context).unfocus(). Phương thức này sẽ giúp bạn ẩn bàn phím khi không cần sử dụng nữa, giúp cải thiện trải nghiệm người dùng. Để sử dụng phương thức này, bạn cần phải có một đối tượng FocusNode được tạo trước đó. Khi bạn muốn ẩn bàn phím, bạn chỉ cần gọi phương thức unfocus() trên đối tượng FocusNode đó. Ví dụ, nếu bạn có một TextField và muốn ẩn bàn phím khi người dùng nhấn vào một nút, bạn có thể sử dụng phương thức FocusScope.of(context).unfocus() trong hàm onPressed của nút đó.
Mở trang câu hỏi này →
ATrue
BFalse
Lời giải
Trong thiết kế giao diện người dùng, 'SingleChildScrollView' là một giải pháp phổ biến để ngăn chặn tình trạng layout bị tràn khi bàn phím mềm (soft keyboard) xuất hiện. Khi người dùng nhập liệu vào một trường văn bản, bàn phím mềm sẽ mở ra và chiếm một phần màn hình. Nếu không có giải pháp thích hợp, layout có thể bị tràn và không hiển thị đầy đủ. 'SingleChildScrollView' giúp giải quyết vấn đề này bằng cách cho phép layout di chuyển khi bàn phím mềm xuất hiện, đảm bảo rằng layout luôn hiển thị đầy đủ trên màn hình.
Mở trang câu hỏi này →
315`GlobalKey<FormState>` is for?4 lựa chọncó code
Đề bài
GlobalKey<FormState>` is for?
AOnly open dialogs
BRandom key
CCall `validate()` / `save()` / `reset()` on the whole form
DReplace `Navigator`
Lời giải
Lời giải
GlobalKey<FormState>

được sử dụng để lưu trữ trạng thái của một form trong ứng dụng Flutter. Nó cho phép bạn gọi các phương thức validate(), save() và reset() trên toàn bộ form. Điều này rất hữu ích khi bạn cần kiểm tra dữ liệu nhập vào của người dùng hoặc lưu trữ dữ liệu vào cơ sở dữ liệu. Bạn có thể sử dụng GlobalKey để gọi các phương thức này trên toàn bộ form, thay vì phải gọi từng phương thức riêng lẻ trên từng widget.

Mở trang câu hỏi này →
AOnly when there is no keyboard
B`TextField` has validators
CInside `Form`, need `validator`/`onSaved` tied to `FormState`
DAlways identical
Lời giải
TextField và TextFormField là hai loại widget trong Flutter dùng để nhập liệu văn bản. TextField chỉ đơn giản là một ô nhập liệu văn bản, còn TextFormField là một loại TextField có thêm các tính năng như kiểm tra dữ liệu (validator), lưu trữ dữ liệu (onSaved) và liên kết với trạng thái của Form. Vì vậy, khi cần sử dụng TextFormField, bạn phải đặt nó trong một Form và liên kết validator/onSaved với trạng thái của Form. Điều này giúp bạn có thể kiểm tra dữ liệu nhập vào và lưu trữ dữ liệu một cách dễ dàng.
Mở trang câu hỏi này →
ASkip the form
BCrash
CSevere error
DField is valid
Lời giải
Khi 'validator' trên 'TextFormField' trả về null, điều đó có nghĩa là trường nhập liệu đã được xác thực thành công. Điều này thường xảy ra khi người dùng nhập dữ liệu hợp lệ, và không có lỗi nào được phát hiện.
Mở trang câu hỏi này →
ATrue
BFalse
Lời giải

Trong Flutter, khi sử dụng Form widget để tạo một biểu mẫu, chúng ta cần một khóa toàn cầu để xác thực và lưu trữ dữ liệu. GlobalKey<FormState> là một đối tượng được sử dụng để quản lý trạng thái của biểu mẫu. Nó cho phép chúng ta xác thực dữ liệu nhập vào và lưu trữ dữ liệu vào cơ sở dữ liệu. Nếu không có khóa toàn cầu này, biểu mẫu sẽ không thể xác thực và lưu trữ dữ liệu. Vì vậy, câu trả lời đúng là True.

Mở trang câu hỏi này →
319Clean Architecture focuses on?4 lựa chọn
AUI design
BDatabase speed
CSeparation of concerns
DAnimations
Lời giải
Clean Architecture là một mô hình kiến trúc phần mềm tập trung vào việc tách biệt các mối quan hệ giữa các phần của hệ thống. Nó nhằm mục đích tạo ra một cấu trúc rõ ràng và dễ hiểu, giúp giảm thiểu sự phức tạp và tăng cường khả năng bảo trì. Clean Architecture nhấn mạnh vào việc tách biệt giữa logic kinh doanh và logic kỹ thuật, giúp các nhà phát triển tập trung vào việc xây dựng các lớp kinh doanh độc lập mà không bị ảnh hưởng bởi các chi tiết kỹ thuật. Điều này giúp hệ thống trở nên linh hoạt và dễ dàng mở rộng.
Mở trang câu hỏi này →
ADismiss keyboard when tapping outside fields
BClear text
CEnable dark mode
DClose the app
Lời giải
Khi sử dụng GestureDetector và unfocus() trong ứng dụng di động, mục đích thường thấy là ngăn chặn bàn phím hiện lên khi người dùng chạm vào khu vực ngoài các trường nhập liệu. Điều này giúp cải thiện trải nghiệm người dùng bằng cách tránh tình trạng bàn phím che khuất các nút hoặc trường nhập liệu quan trọng. GestureDetector cho phép ứng dụng phản ứng với các hành động chạm vào màn hình, trong khi unfocus() giúp loại bỏ bàn phím khi người dùng chạm vào khu vực ngoài các trường nhập liệu. Kết hợp cả hai tính năng này giúp tạo ra một ứng dụng di động mượt mà và dễ sử dụng hơn.
Mở trang câu hỏi này →
Amain.dart
BrunApp()
Cvalidator
DThemeData
Lời giải
Trong một dự án Flutter tiêu chuẩn, tệp nào phục vụ như điểm nhập vào của ứng dụng?
Mở trang câu hỏi này →
Aimplements
Bmain.dart
Cvalidator
DMediaQuery
Lời giải
Trong Dart OOP, từ khóa nào cho phép một lớp thực hiện một giao diện bằng cách cung cấp thực hiện của riêng nó cho tất cả các phương thức? Trong Dart, từ khóa "implements" được sử dụng để cho phép một lớp thực hiện một giao diện. Điều này có nghĩa là lớp đó phải cung cấp thực hiện của riêng nó cho tất cả các phương thức được định nghĩa trong giao diện. Điều này cho phép lớp đó thực hiện giao diện và sử dụng các phương thức được định nghĩa trong giao diện. Ví dụ, nếu chúng ta có một giao diện tên "MyInterface" với một phương thức "myMethod()", chúng ta có thể tạo một lớp tên "MyClass" thực hiện giao diện "MyInterface" bằng cách sử dụng từ khóa "implements" và cung cấp thực hiện của riêng nó cho phương thức "myMethod()".
Mở trang câu hỏi này →
ATrue
BFalse
Lời giải
Khi đặt 'autovalidateMode' thành 'onUserInteraction', người dùng sẽ nhận được phản hồi xác thực ngay lập tức khi nhập liệu. Điều này có nghĩa là khi người dùng nhập dữ liệu, hệ thống sẽ kiểm tra ngay lập tức và hiển thị kết quả xác thực. Điều này giúp người dùng nhận biết được lỗi ngay lập tức và có thể điều chỉnh dữ liệu của mình một cách nhanh chóng và hiệu quả. Tính năng này rất hữu ích khi người dùng nhập dữ liệu lớn hoặc phức tạp, giúp giảm thiểu thời gian và công sức cần thiết để xác thực dữ liệu.
Mở trang câu hỏi này →
ATrue
BFalse
Lời giải
Thuộc tính 'TextInputAction.done' cho biết bàn phím nên hiển thị nút hoàn thành thay vì nút chuyển sang trường tiếp theo. Khi bạn sử dụng 'TextInputAction.done', bàn phím sẽ hiển thị một nút hoàn thành thay vì nút chuyển sang trường tiếp theo khi nhập xong. Điều này giúp người dùng dễ dàng xác nhận và hoàn thành việc nhập liệu.
Mở trang câu hỏi này →