Việc làm

3 ngày trước · Hồ Chí Minh · Tại văn phòng

Junior Android Developer (Kotlin/Java)

Motorist Pte Ltd · Mobile Application Developer

Xem mô tả & ứng tuyển trên ITviecMô tả công việc, lương và ứng tuyển nằm ở ITviec.

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, C/C++ & Embedded). 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.

  1. 01So sánh các kiến trúc MVC, MVVM, MVI/Clean Architecture cho ứng dụng mobile.Mobile (Android, iOS, Flutter)

    Gợi ý trả lời

    Mục tiêu chung là tách UI khỏi logic để dễ test và dễ bảo trì.

    • MVC: dễ bắt đầu nhưng trên iOS UIKit thường thành "Massive View Controller".
    • MVVM: ViewModel giữ state và logic, View chỉ quan sát và hiển thị. Hợp tự nhiên với SwiftUI, Jetpack Compose (ViewModel + StateFlow) và Flutter.
    • MVI / Unidirectional data flow: một state bất biến duy nhất cho màn hình, UI gửi intent, reducer tạo state mới. Dễ debug, hợp với UI khai báo.
    • Clean Architecture: chia layer presentation / domain / data, repository che giấu nguồn dữ liệu (API, cache, DB).

    Người phỏng vấn muốn nghe: lý do chọn kiến trúc cho dự án cụ thể. App nhỏ không cần đủ use case và mapper ở mọi tầng; app lớn nhiều team thì nên chia module theo tính năng.

    Ôn thêm câu hỏi Mobile (Android, iOS, Flutter) →
  2. 02Danh 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

    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 (key trong LazyColumn, ValueKey trong Flutter, Identifiable trong SwiftUI) để không tạo lại item không cần thiết.
    • Cập nhật một phần: DiffUtil / ListAdapter thay vì notifyDataSetChanged.
    • Compose: state ổn định để tránh recompose thừa; Flutter: dùng ListView.builder và const widget.
    • 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.

    Ôn thêm câu hỏi Mobile (Android, iOS, Flutter) →
  3. 03Trì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

    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 onResume mà quên huỷ ở onPause, gây rò rỉ và hao pin. Trên Android nên thu thập Flow bằng repeatOnLifecycle.

    Ôn thêm câu hỏi Mobile (Android, iOS, Flutter) →
  4. 04Bộ nhớ JVM gồm những vùng nào? Garbage Collector hoạt động ra sao và Java có bị memory leak không?Java

    Gợi ý trả lời

    Hai vùng chính: stack (mỗi thread một stack, chứa biến cục bộ và tham chiếu) và heap (chứa object, dùng chung). Ngoài ra có Metaspace chứa thông tin class.

    • GC tìm các object không còn được tham chiếu từ "GC roots" (biến trên stack, field static...) và thu hồi.
    • Heap chia theo thế hệ: object mới nằm ở young generation, sống lâu thì được chuyển lên old generation.
    • G1 là GC mặc định; ZGC hợp khi cần pause rất ngắn với heap lớn.

    Java vẫn leak khi object không dùng nữa mà vẫn còn tham chiếu:

    • Cache hoặc static Map chỉ thêm, không bao giờ xoá.
    • ThreadLocal không remove() trong thread pool.
    • Listener đăng ký mà không huỷ.

    Người phỏng vấn muốn nghe: phân biệt được OutOfMemoryError: Java heap space với lỗi Metaspace, và biết dùng heap dump để tìm ai đang giữ object.

    Ôn thêm câu hỏi Java →
  5. 05Phân biệt == và equals(). Vì sao override equals() thì phải override cả hashCode()?Java · Junior

    Gợi ý trả lời

    == so sánh tham chiếu (hai biến có trỏ cùng một object không), còn equals() so sánh nội dung theo logic bạn định nghĩa.

    • Hợp đồng: hai object equals nhau thì bắt buộc có cùng hashCode.
    • HashMap/HashSet dùng hashCode để chọn bucket trước, rồi mới dùng equals để so trong bucket. Nếu chỉ override equals, hai object "bằng nhau" có thể rơi vào hai bucket khác nhau, nên set.contains(x) trả về false dù đã add.
    • Với Java 16+, record tự sinh equals/hashCode/toString theo các field.

    Hay sai: so sánh String hoặc Integer bằng ==. Nó có thể chạy đúng nhờ string pool hoặc cache Integer từ -128 đến 127, rồi sai với giá trị khác.

    Ôn thêm câu hỏi Java →
  6. 06Con trỏ và tham chiếu (reference) trong C++ khác nhau thế nào?C/C++ & Embedded · Junior

    Gợi ý trả lời

    Con trỏ là biến chứa địa chỉ, có thể nullptr và trỏ sang đối tượng khác. Tham chiếu là tên gọi khác của một đối tượng đã tồn tại, phải khởi tạo ngay và không gán lại được.

    int x = 1, y = 2;
    int* p = &x;  p = &y;   // đổi đối tượng được trỏ
    int& r = x;   r = y;    // gán giá trị y cho x
    
    • Truyền tham số: dùng const T& cho đối tượng lớn chỉ đọc, T& khi cần sửa, con trỏ khi tham số có thể vắng mặt.
    • Có con trỏ tới con trỏ và phép toán số học trên con trỏ; tham chiếu thì không.

    Hay sai: trả về tham chiếu hoặc con trỏ tới biến cục bộ. Biến bị huỷ khi hàm kết thúc và dùng nó là undefined behavior.

    Ôn thêm câu hỏi C/C++ & Embedded →
  7. 07Là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

    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:

    • ViewModel sống qua thay đổi cấu hình nhưng không sống qua process death.
    • SavedStateHandle (trong ViewModel) hoặc rememberSaveable (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ó @SceneStorage cho 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 kill khi app ở background.

    Ôn thêm câu hỏi Mobile (Android, iOS, Flutter) →
  8. 08Trong 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

    StatelessWidget chỉ phụ thuộc tham số đầu vào; StatefulWidget có một object State riê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ại build cho 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 setState sau khi widget đã bị huỷ (sau một await); hãy kiểm tra mounted. Đặt setState ở widget quá cao làm build lại cả màn hình, nên tách nhỏ widget và dùng const constructor.

    Khi state dùng chung nhiều màn hình, chuyển sang Provider, Riverpod hoặc Bloc.

    Ôn thêm câu hỏi Mobile (Android, iOS, Flutter) →
  9. 09Why are you interested in this role?Phỏng vấn tiếng Anh

    Gợi ý trả lời

    "I've been working on payment systems for three years, and I'm really interested in building products at a larger scale. From the job description, your team is redesigning the transaction platform, which matches my experience and what I want to learn next. I also like that you have a strong engineering culture with code reviews and technical sharing. I believe I can contribute quickly and keep growing here."

    Mẹo: nối ba ý: kinh nghiệm của bạn, điều công ty đang làm, điều bạn muốn học. Dùng chi tiết từ JD để cho thấy bạn đã tìm hiểu. Tránh mở đầu bằng lương hay "because your company is big".

    Ôn thêm câu hỏi Phỏng vấn tiếng Anh →
  10. 10Bạn nghĩ sao về việc làm thêm giờ (OT)?Câu hỏi hành vi & văn hoá

    Gợi ý trả lời

    Trả lời thẳng thắn và cân bằng: sẵn sàng khi thật sự cần, nhưng không coi OT kéo dài là bình thường.

    Câu mẫu: "Em sẵn sàng làm thêm khi có việc gấp như sự cố production hay trước một đợt release quan trọng. Nhưng nếu OT diễn ra thường xuyên, em nghĩ cần xem lại cách estimate hoặc phạm vi, và em sẽ chủ động nêu điều đó với team. Em cũng muốn hỏi thêm: ở team mình OT thường xảy ra trong trường hợp nào và được tính như thế nào ạ?"

    Đây cũng là lúc bạn tìm hiểu ngược: OT có được trả lương hoặc nghỉ bù theo quy định không, tần suất ra sao. Câu trả lời của họ cho bạn biết nhiều về văn hoá công ty.

    Hay sai: hứa "OT thoải mái" để lấy điểm, rồi vào làm mới thấy không chịu nổi.

    Ôn thêm câu hỏi Câu hỏi hành vi & văn hoá →

Bạn đã phỏng vấn ở Motorist Pte 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