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), Java, JavaScript & TypeScript). 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.
01Chọ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.
02Trình bày vòng đời (lifecycle) của Activity trên Android hoặc của app/view trên iOS.Mobile (Android, iOS, Flutter) · Junior
Gợi ý trả lời
Ôn thêm câu hỏi Mobile (Android, iOS, Flutter) →Vòng đời cho biết khi nào hệ điều hành tạo, hiển thị, tạm dừng và huỷ màn hình, để bạn khởi tạo và giải phóng tài nguyên đúng lúc.
- Android Activity:
onCreate→onStart→onResume(đang tương tác) →onPause→onStop→onDestroy. Xoay màn hình mặc định sẽ huỷ và tạo lại Activity. - iOS UIKit:
viewDidLoad(một lần) →viewWillAppear→viewDidAppear→viewWillDisappear→viewDidDisappear. Trạng thái app: active, inactive, background. - SwiftUI / Compose: nghĩ theo state và các hook như
.task,onAppear,LaunchedEffect,DisposableEffect.
Hay sai: đăng ký listener hoặc sensor trong
onResumemà quên huỷ ởonPause, gây rò rỉ và hao pin. Trên Android nên thu thập Flow bằngrepeatOnLifecycle.- Android Activity:
03Làm sao giữ dữ liệu khi xoay màn hình hoặc khi app bị hệ điều hành kill ở background?Mobile (Android, iOS, Flutter) · Junior
Gợi ý trả lời
Ôn thêm câu hỏi Mobile (Android, iOS, Flutter) →Có hai tình huống khác nhau: thay đổi cấu hình (xoay màn hình, đổi ngôn ngữ) và process death (hệ điều hành kill app để lấy RAM).
Android:
ViewModelsống qua thay đổi cấu hình nhưng không sống qua process death.SavedStateHandle(trong ViewModel) hoặcrememberSaveable(Compose) lưu trạng thái nhỏ như id, nội dung form, vị trí cuộn.- Dữ liệu lớn hoặc quan trọng lưu bền vững bằng Room hoặc DataStore.
iOS: SwiftUI có
@SceneStoragecho trạng thái UI nhỏ; UIKit có state restoration; dữ liệu thật lưu bằng SwiftData, Core Data hoặc file.Người phỏng vấn muốn nghe: bạn biết cách kiểm thử process death, vd. bật "Don't keep activities" hoặc dùng
adb shell am killkhi app ở background.04Phân biệt
==vàequals(). Vì sao overrideequals()thì phải override cảhashCode()?Java · JuniorGợi ý trả lời
Ôn thêm câu hỏi Java →==so sánh tham chiếu (hai biến có trỏ cùng một object không), cònequals()so sánh nội dung theo logic bạn định nghĩa.- Hợp đồng: hai object
equalsnhau thì bắt buộc có cùnghashCode. HashMap/HashSetdùnghashCodeđể chọn bucket trước, rồi mới dùngequalsđể so trong bucket. Nếu chỉ overrideequals, hai object "bằng nhau" có thể rơi vào hai bucket khác nhau, nênset.contains(x)trả vềfalsedù đã add.- Với Java 16+,
recordtự sinhequals/hashCode/toStringtheo các field.
Hay sai: so sánh
StringhoặcIntegerbằng==. Nó có thể chạy đúng nhờ string pool hoặc cacheIntegertừ -128 đến 127, rồi sai với giá trị khác.- Hợp đồng: hai object
05Vì sao
Stringlà immutable? Khi nào dùngStringBuilderthay choString?Java · JuniorGợi ý trả lời
Ôn thêm câu hỏi Java →Stringbất biến: mọi thao tác "sửa" đều tạo object mới. Nhờ vậy nó an toàn khi chia sẻ giữa nhiều thread, dùng làm key choHashMapđược (hash không đổi) và JVM có thể dùng chung qua string pool.- Nối chuỗi trong vòng lặp bằng
+tạo nhiều object trung gian, nên dùngStringBuilder:
var sb = new StringBuilder(); for (String s : items) sb.append(s).append(','); String result = sb.toString();StringBuffergiốngStringBuildernhưng các method cósynchronized, chậm hơn và hiếm khi cần.- Nối vài chuỗi trên một dòng thì cứ dùng
+, compiler đã tối ưu sẵn.
Người phỏng vấn muốn nghe: bạn hiểu lý do thiết kế (an toàn, hash, pool), không chỉ thuộc định nghĩa.
- Nối chuỗi trong vòng lặp bằng
06
==và===khác nhau thế nào? Những giá trị nào là falsy?JavaScript & TypeScript · JuniorGợi ý trả lời
Ôn thêm câu hỏi JavaScript & TypeScript →===so sánh cả kiểu lẫn giá trị.==ép kiểu trước khi so, nên cho ra kết quả khó đoán:"0" == 0làtrue,[] == falsecũngtrue.- Các giá trị falsy:
false,0,-0,0n,"",null,undefined,NaN. Mọi thứ khác là truthy, kể cả[],{}và"0". NaN === NaNlàfalse; dùngNumber.isNaN(x).- Ngoại lệ hay được chấp nhận:
x == nullđể bắt cảnulllẫnundefined.
Hay sai: viết
const page = input || 1. Khi người dùng nhập0, giá trị bị thay bằng1. Dùng nullish coalescinginput ?? 1để chỉ thay khi lànullhoặcundefined.- Các giá trị falsy:
07Trong Flutter, StatelessWidget và StatefulWidget khác nhau thế nào? setState hoạt động ra sao?Mobile (Android, iOS, Flutter) · Junior
Gợi ý trả lời
Ôn thêm câu hỏi Mobile (Android, iOS, Flutter) →StatelessWidgetchỉ phụ thuộc tham số đầu vào;StatefulWidgetcó một objectStateriêng, tồn tại qua các lần build, để giữ dữ liệu thay đổi theo thời gian.setStateđánh dấu widget "dirty"; ở frame kế tiếp Flutter gọi lạibuildcho widget đó và cây con.- Widget là cấu hình nhẹ, tạo lại liên tục; Element và RenderObject mới là phần được tái sử dụng.
- Dọn dẹp controller, stream subscription trong
dispose.
void _increment() => setState(() => _count++);Hay sai: gọi
setStatesau khi widget đã bị huỷ (sau mộtawait); hãy kiểm tramounted. ĐặtsetStateở widget quá cao làm build lại cả màn hình, nên tách nhỏ widget và dùngconstconstructor.Khi state dùng chung nhiều màn hình, chuyển sang Provider, Riverpod hoặc Bloc.
08Vì sao không được làm việc nặng trên main thread (UI thread)? Bạn xử lý thế nào?Mobile (Android, iOS, Flutter) · Junior
Gợi ý trả lời
Ôn thêm câu hỏi Mobile (Android, iOS, Flutter) →Main thread vẽ UI và nhận thao tác người dùng. Mỗi frame chỉ có khoảng 16 ms (60 Hz) hoặc ít hơn với màn 120 Hz, nên việc nặng sẽ gây giật, lag; Android chặn quá lâu sẽ báo ANR.
Cách xử lý theo nền tảng:
- Android: coroutines với
Dispatchers.IOcho I/O,Dispatchers.Defaultcho tính toán, sau đó cập nhật state trên Main. - iOS:
async/awaitvới Swift concurrency; code UI đánh dấu@MainActor. - Flutter: Dart chạy một isolate; I/O bất đồng bộ không chặn, nhưng tính toán nặng (parse JSON lớn, xử lý ảnh) nên đẩy sang isolate khác bằng
Isolate.runhoặccompute.
Hay sai: nghĩ
asynclà đủ. Hàm async trong Dart vẫn chạy trên cùng isolate, nên vòng lặp tính toán nặng vẫn làm đơ UI.- Android: coroutines với
09Kotlin 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:
10Vì sao bạn muốn rời công ty hiện tại?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á →Trả lời thật nhưng hướng về phía trước: nói điều bạn đang tìm kiếm, không kể xấu nơi cũ.
Lý do chấp nhận được: muốn thử thách mới, muốn làm sản phẩm, dự án kết thúc, công ty tái cấu trúc, thu nhập chưa tương xứng (nói khéo).
Câu mẫu: "Em đã làm 2 năm ở dự án outsourcing, học được nhiều về quy trình và làm việc với khách nước ngoài. Giờ em muốn gắn bó lâu dài với một sản phẩm để thấy được tác động của những gì mình làm, và vị trí bên mình đúng hướng đó."
Hay sai: chê sếp, chê đồng nghiệp, kể chuyện drama. Người phỏng vấn sẽ nghĩ bạn cũng sẽ nói về công ty họ như vậy. Nếu nhảy việc nhiều, chuẩn bị lời giải thích cho từng lần.
Bạn đã phỏng vấn ở BSC – Chứng khoán BIDV?
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