10 câu hỏi có thể gặp khi phỏng vấn
Chọn theo kỹ năng và cấp của tin (Mobile (Android, iOS, Flutter), System Design & Kiến trúc). Gợi ý trả lời do Drama Công Ty biên soạn để bạn ôn nhanh, không phải đề của công ty.
01Danh sách dài (RecyclerView, LazyColumn, List, ListView) bị giật khi cuộn. Bạn tối ưu thế nào?Mobile (Android, iOS, Flutter)
Gợi ý trả lời
Ôn thêm câu hỏi Mobile (Android, iOS, Flutter) →Trước tiên đo bằng công cụ (Android Studio Profiler, Instruments, Flutter DevTools), sau đó xử lý các nguyên nhân phổ biến:
- Ảnh: tải bất đồng bộ, resize đúng kích thước hiển thị, có cache (Coil, Glide, Kingfisher, cached_network_image).
- Công việc trong bind/build: không format ngày, parse dữ liệu hay tính toán mỗi lần vẽ item; chuẩn bị sẵn trong ViewModel.
- Key ổn định: dùng id làm key (
keytrongLazyColumn,ValueKeytrong Flutter,Identifiabletrong SwiftUI) để không tạo lại item không cần thiết. - Cập nhật một phần:
DiffUtil/ListAdapterthay vìnotifyDataSetChanged. - Compose: state ổn định để tránh recompose thừa; Flutter: dùng
ListView.buildervàconstwidget. - Phân trang dữ liệu (Paging 3, infinite scroll).
Người phỏng vấn muốn nghe: bạn đo trước và sau, không chỉ sửa theo cảm tính.
02Bạn phát hiện và xử lý memory leak trong ứng dụng mobile thế nào?Mobile (Android, iOS, Flutter) · Senior
Gợi ý trả lời
Ôn thêm câu hỏi Mobile (Android, iOS, Flutter) →Leak trên mobile thường do một object sống lâu giữ tham chiếu tới object lẽ ra phải được giải phóng, như màn hình, view hay context.
- Android: giữ
Activity/Contexttrong singleton hoặc biến static, listener không huỷ đăng ký, coroutine hoặc callback sống lâu hơn màn hình. Phát hiện bằng LeakCanary và Memory Profiler (heap dump). - iOS: ARC không tự phá được retain cycle, vd. closure giữ
selftrong khiselfgiữ closure, delegate khai báostrong. Dùng[weak self],weak var delegate. Phát hiện bằng Memory Graph Debugger và Instruments (Leaks, Allocations). - Flutter: quên
disposecontroller,StreamSubscription,Timer. Xem bằng DevTools Memory.
Người phỏng vấn muốn nghe: quy trình tái hiện (mở rồi đóng màn hình nhiều lần, xem số instance có giảm không) và một ca bạn đã sửa thật.
- Android: giữ
03Thiết kế tính năng offline-first: app vẫn dùng được khi mất mạng và đồng bộ khi có mạng lại.Mobile (Android, iOS, Flutter) · Senior
Gợi ý trả lời
Ôn thêm câu hỏi Mobile (Android, iOS, Flutter) →Lấy database cục bộ làm nguồn sự thật cho UI: UI chỉ đọc từ DB local, tầng sync lo việc đồng bộ với server.
- Lưu trữ: Room, SwiftData / Core Data, Drift hoặc Isar (Flutter). UI quan sát dữ liệu qua Flow,
@Queryhoặc Stream. - Ghi khi offline: lưu thay đổi vào hàng đợi (outbox) kèm trạng thái pending; khi có mạng thì gửi lên, nhận phản hồi rồi đánh dấu đã đồng bộ.
- Lập lịch đồng bộ: WorkManager (Android), BGTaskScheduler (iOS), có ràng buộc mạng và backoff khi lỗi.
- Xung đột: chọn chiến lược như last-write-wins theo timestamp server, version number, hoặc cho người dùng chọn với dữ liệu quan trọng.
- Request cần idempotent (gửi kèm id do client sinh) để retry không tạo bản ghi trùng.
Người phỏng vấn muốn nghe: bạn tính tới đồng bộ từng phần (delta sync) và cách hiển thị trạng thái "chưa đồng bộ" cho người dùng.
- Lưu trữ: Room, SwiftData / Core Data, Drift hoặc Isar (Flutter). UI quan sát dữ liệu qua Flow,
04Khi nào dùng message queue như Kafka hay RabbitMQ? Hai công cụ này khác nhau thế nào?System Design & Kiến trúc
Gợi ý trả lời
Ôn thêm câu hỏi System Design & Kiến trúc →Message queue tách bên gửi và bên nhận: xử lý bất đồng bộ, hấp thụ tải đột biến, cho nhiều hệ thống cùng phản ứng với một sự kiện.
- RabbitMQ: message broker truyền thống, định tuyến linh hoạt qua exchange (direct, topic, fanout), message bị xoá sau khi consumer ack. Hợp với hàng đợi tác vụ như gửi email, xử lý ảnh.
- Kafka: log phân tán chỉ ghi nối, message được giữ theo thời gian cấu hình, consumer tự quản lý offset nên đọc lại được. Thứ tự chỉ đảm bảo trong từng partition. Hợp với event streaming, thông lượng lớn, nhiều consumer group.
Lưu ý khi dùng:
- Mặc định nên coi là at-least-once, nên consumer phải idempotent.
- Có dead letter queue cho message lỗi lặp lại.
- Theo dõi consumer lag.
Người phỏng vấn muốn nghe: lý do chọn gắn với nhu cầu cụ thể, không chọn Kafka chỉ vì nghe "xịn".
05Định lý CAP là gì? Strong consistency và eventual consistency áp dụng thế nào trong thực tế?System Design & Kiến trúc
Gợi ý trả lời
Ôn thêm câu hỏi System Design & Kiến trúc →CAP nói rằng khi xảy ra phân mảnh mạng (Partition), hệ phân tán phải chọn giữa Consistency (mọi node trả dữ liệu mới nhất hoặc báo lỗi) và Availability (luôn trả lời, có thể bằng dữ liệu cũ). Khi mạng bình thường, trade-off thực tế là giữa độ trễ và tính nhất quán (mô hình PACELC).
- Strong consistency: cần cho số dư tài khoản, tồn kho, đặt chỗ, nơi đọc dữ liệu cũ gây thiệt hại thật.
- Eventual consistency: chấp nhận được cho lượt thích, bảng tin, số người xem, kết quả tìm kiếm.
Một hệ thống thường kết hợp cả hai theo từng loại dữ liệu. Có những mức ở giữa như read-your-writes: người vừa sửa thì phải thấy thay đổi của mình, người khác thấy chậm vài giây cũng không sao.
Hay sai: nói "chọn 2 trong 3" như thể có thể bỏ P. Với hệ phân tán, phân mảnh mạng là chuyện chắc chắn xảy ra.
06Bảo mật ứng dụng mobile: lưu token, gọi API và chống dịch ngược thế nào?Mobile (Android, iOS, Flutter) · Senior
Gợi ý trả lời
Ôn thêm câu hỏi Mobile (Android, iOS, Flutter) →Coi app là môi trường không tin cậy: mọi thứ đóng gói trong app đều có thể bị đọc, nên kiểm soát quan trọng nhất phải nằm ở server.
- Lưu token: Keychain (iOS), Keystore kết hợp EncryptedSharedPreferences hoặc DataStore mã hoá (Android),
flutter_secure_storage. Không lưu trong SharedPreferences / UserDefaults thường hay log ra console. - Phiên đăng nhập: access token ngắn hạn, refresh token xoay vòng; đăng nhập OAuth dùng PKCE.
- Mạng: chỉ HTTPS; có thể dùng certificate pinning nhưng cần kế hoạch xoay chứng chỉ.
- Secret: không nhúng API key quan trọng trong app; gọi qua backend.
- Chống can thiệp: obfuscation (R8), Play Integrity API, App Attest để server xác minh app thật.
Hay sai: tin rằng obfuscation là đủ. Nó chỉ làm chậm kẻ tấn công.
- Lưu token: Keychain (iOS), Keystore kết hợp EncryptedSharedPreferences hoặc DataStore mã hoá (Android),
07Chọn native (Kotlin/Swift) hay cross-platform (Flutter, React Native) cho một dự án mới? Bạn cân nhắc gì?Mobile (Android, iOS, Flutter) · Senior
Gợi ý trả lời
Ôn thêm câu hỏi Mobile (Android, iOS, Flutter) →Không có đáp án chung; quyết định dựa trên yêu cầu sản phẩm, đội ngũ và chi phí dài hạn.
- Cross-platform (Flutter, React Native, hoặc Kotlin Multiplatform để chia sẻ logic): một codebase cho hai nền tảng, ra mắt nhanh, hợp với app nghiệp vụ, thương mại điện tử, nội bộ.
- Native: cần tích hợp sâu với hệ điều hành (widget, camera hoặc Bluetooth phức tạp, xử lý nền), hiệu năng đồ hoạ cao, hoặc muốn dùng tính năng mới của OS ngay khi ra mắt.
Các yếu tố cần cân nhắc:
- Kỹ năng hiện có của team và khả năng tuyển người.
- Mức độ tuỳ biến UI theo từng nền tảng.
- Chi phí viết plugin native khi thư viện không có sẵn.
- Kích thước app và thời gian khởi động.
Người phỏng vấn muốn nghe: bạn đưa ra lập luận gắn với bối cảnh cụ thể và nhắc tới phương án lai, vd. thêm màn hình Flutter vào app native.
08Kotlin coroutines: suspend function, scope, dispatcher và structured concurrency là gì?Mobile (Android, iOS, Flutter)
Gợi ý trả lời
Ôn thêm câu hỏi Mobile (Android, iOS, Flutter) →Coroutine là tác vụ nhẹ có thể tạm dừng (suspend) mà không chặn thread.
suspend funchỉ gọi được từ coroutine hoặc từ suspend function khác.- Scope quyết định vòng đời:
viewModelScope,lifecycleScopetự huỷ coroutine khi ViewModel hoặc màn hình bị huỷ. - Dispatcher quyết định chạy ở đâu:
Main,IO,Default. - Structured concurrency: coroutine con gắn với cha; cha huỷ thì con huỷ, con lỗi thì lan lên cha (trừ khi dùng
SupervisorJob).
viewModelScope.launch { val user = withContext(Dispatchers.IO) { repo.fetchUser() } _state.value = UiState.Success(user) }Hay sai: dùng
GlobalScopegây rò rỉ; bắtCancellationExceptiontrongcatch (e: Exception)mà không ném lại, làm hỏng cơ chế huỷ.- Scope quyết định vòng đời:
09Tell me about a difficult problem you solved.Phỏng vấn tiếng Anh
Gợi ý trả lời
Ôn thêm câu hỏi Phỏng vấn tiếng Anh →"Our report page became very slow as the data grew, sometimes taking more than a minute. I checked the query plans and found that a few queries were scanning entire tables. I added the right indexes, rewrote one query to avoid unnecessary joins, and cached the daily summary. The page then loaded in a few seconds, and the support team stopped receiving complaints about it."
Mẹo: dùng STAR và thì quá khứ đơn cho cả câu chuyện ("I found", "I added", không phải "I find", "I add"). Đây là lỗi rất hay gặp khi nói nhanh. Kết bằng kết quả cụ thể, đo được nếu có.
10Mức lương mong muốn của bạn là bao nhiêu?Câu hỏi hành vi & văn hoá
Gợi ý trả lời
Ôn thêm câu hỏi Câu hỏi hành vi & văn hoá →Tìm hiểu trước mặt bằng lương cho vị trí và số năm kinh nghiệm (dữ liệu lương trên Drama Công Ty, bạn bè cùng ngành), rồi đưa ra một khoảng có căn cứ.
- Nói rõ gross hay net. Gross là lương trước khi trừ bảo hiểm bắt buộc và thuế thu nhập cá nhân; net là số thực nhận.
- Hỏi tổng thu nhập: lương tháng 13 (không bắt buộc theo luật), thưởng, chu kỳ review lương, bảo hiểm sức khoẻ.
- Lương thử việc theo luật tối thiểu bằng 85% lương chính thức; nhiều công ty trả 100%, cứ hỏi rõ.
Câu mẫu: "Dựa trên kinh nghiệm và mặt bằng thị trường, em mong muốn khoảng X đến Y triệu gross. Em cũng muốn hiểu thêm về thưởng và review lương bên mình."
Hay sai: nói "tuỳ công ty" (dễ bị trả thấp), hoặc khai khống lương hiện tại.
Bạn đã phỏng vấn ở Grab (Vietnam) Ltd.?
Kể lại các vòng và câu hỏi đã gặp (ẩn danh) để người sau ôn đúng trọng tâm.
Chia sẻ kinh nghiệm phỏng vấn