Dưới đây là danh sách các câu hỏi thường gặp trong buổi phỏng vấn cho vị trí lập trình viên Android mà mình đã tổng hợp. Trước khi bước vào buổi phỏng vấn, hãy xem lại các câu hỏi này để chuẩn bị tốt nhất, biết đâu có thể gặp những câu hỏi “tủ”. Mình sẽ bỏ qua những câu hỏi cơ bản như định nghĩa về Activity hay liệt kê vòng đời của Activity và Fragment, và sẽ tập trung vào những câu hỏi thường bị bỏ qua. Các câu trả lời sẽ ngắn gọn, tập trung vào các ý chính, và bạn có thể tìm hiểu chi tiết hơn bằng cách tra cứu các từ khóa.

Application là gì?
Lớp Application trong Android là lớp cơ sở của ứng dụng, chứa tất cả các thành phần khác như Activity và Service. Nó được khởi tạo đầu tiên khi ứng dụng của bạn bắt đầu.

Context là gì?
Context là đối tượng cung cấp thông tin về môi trường của hệ thống, cho phép truy cập đến resources, database, và preferences. Có hai loại chính là Application Context (gắn liền với vòng đời của ứng dụng) và Activity Context (gắn liền với vòng đời của Activity).

Tại sao bytecode không thể chạy trong Android?
Android sử dụng Dalvik Virtual Machine (DVM) và Android Runtime (ART) thay vì Java Virtual Machine (JVM), vì vậy bytecode của Java không thể chạy trực tiếp trên Android.

BuildType trong Gradle là gì?
BuildType trong Gradle xác định cách ứng dụng được xây dựng, chẳng hạn như có sử dụng ProGuard hay không. Nó kết hợp với Product Flavor để tạo ra các build variant.

Quá trình build ứng dụng trong Android
Quá trình này bao gồm nhiều bước từ việc dịch mã nguồn Java/Kotlin thành bytecode, rồi chuyển thành mã máy được Android Runtime thực thi.

Khi nào onDestroy() được gọi mà không có onPause() và onStop()?
Khi bạn gọi finish() trong onCreate(), onDestroy() sẽ được gọi ngay mà không đi qua onPause() và onStop().

Tại sao chỉ nên gọi setContentView() trong onCreate()?
Vì onCreate() chỉ được gọi một lần khi Activity được tạo. Nếu gọi setContentView() trong onResume() hoặc onStart(), bạn sẽ tốn tài nguyên không cần thiết vì hai phương thức này được gọi nhiều lần.

Phân biệt giữa Service, IntentService, AsyncTask và Thread

  1. Service chạy ngầm, không có giao diện người dùng.
  2. AsyncTask giúp thực hiện tác vụ bất đồng bộ và cập nhật UI.
  3. IntentService xử lý các yêu cầu bất đồng bộ một cách lần lượt trong background.
  4. Thread là một luồng thực thi độc lập.

Job Scheduling là gì?
API này giúp lập lịch các tác vụ tối ưu hóa hệ thống dựa trên tình trạng kết nối, pin, và bộ nhớ. Nó rất hữu ích cho các tác vụ cần chạy nền mà không yêu cầu tức thời.

Mối quan hệ giữa AsyncTask và Activity?
AsyncTask không gắn với vòng đời của Activity. Điều này có thể dẫn đến các vấn đề như cập nhật nhầm giao diện hoặc rò rỉ bộ nhớ khi Activity bị hủy.

onTrimMemory() là gì?
Phương thức này được gọi khi hệ thống yêu cầu thu hồi bộ nhớ. Bạn có thể xử lý việc giải phóng tài nguyên không cần thiết để ứng dụng không bị hệ thống hủy.

AIDL và Messenger Queue khác nhau thế nào?
AIDL hỗ trợ truyền thông điệp giữa các tiến trình một cách song song, trong khi Messenger Queue xử lý các thông điệp tuần tự.

ThreadPool là gì?
ThreadPool giúp quản lý và tái sử dụng các luồng, tiết kiệm tài nguyên CPU hơn so với việc tạo nhiều Thread riêng biệt.

Sự khác biệt giữa Serializable và Parcelable?
Serializable là một interface chuẩn của Java, trong khi Parcelable là interface của Android. Parcelable hiệu quả hơn nhưng yêu cầu triển khai thủ công.

Cập nhật UI từ background service như thế nào?
Bạn có thể sử dụng LocalBroadcastReceiver hoặc Handler để truyền dữ liệu từ service lên UI.

Sự khác biệt giữa add và replace fragment trong backstack?

  1. add giữ lại fragment hiện có và thêm fragment mới lên trên.
  2. replace thay thế fragment hiện tại bằng một fragment mới.

Tại sao nên truyền tham số vào Fragment qua Bundle?
Bundle giúp hệ thống khôi phục lại trạng thái của Fragment khi cấu hình thiết bị thay đổi.

Retained Fragment là gì?
Retained Fragment không bị hủy và tạo lại khi cấu hình thiết bị thay đổi, giúp giữ lại dữ liệu và trạng thái.

Phân biệt giữa FragmentPagerAdapter và FragmentStatePagerAdapter

  1. FragmentPagerAdapter lưu tất cả các fragment trong bộ nhớ, thích hợp cho số lượng ít fragment.
  2. FragmentStatePagerAdapter chỉ giữ lại trạng thái của fragment, tiết kiệm bộ nhớ hơn cho các tập dữ liệu lớn.

Sự khác biệt giữa margin và padding?

  1. Padding là khoảng cách bên trong view.
  2. Margin là khoảng cách bên ngoài view.

ViewGroup là gì?
ViewGroup là một container chứa các view hoặc view khác. Nó khác View ở chỗ nó không phản hồi tương tác người dùng mà chỉ chứa các thành phần khác.

Sự khác biệt giữa hình ảnh PNG và hình ảnh nine-patch
Nine-patch cho phép bạn co giãn hình ảnh mà không làm mất chất lượng các góc. Nó thường được sử dụng cho hình nền hoặc các tài nguyên giao diện.

Khi nào nên sử dụng FrameLayout?
FrameLayout phù hợp khi bạn cần chứa một view duy nhất hoặc chồng các view lên nhau.

Adapter là gì?
Adapter chịu trách nhiệm chuyển đổi từng entry trong dữ liệu thành View, sau đó được thêm vào AdapterView (ListView, RecyclerView) để hiển thị.

Tóm tắt quá trình tạo một custom View.

  1. Tạo một lớp kế thừa từ View.
  2. Định nghĩa các thuộc tính tùy chỉnh trong file res/values/attrs.xml.
  3. Khởi tạo các thuộc tính trong constructor.
  4. Ghi đè các phương thức như onSizeChanged() hoặc onMeasure().
  5. Vẽ View bằng cách ghi đè onDraw().

Cách tối ưu hóa việc sử dụng View.

  1. Kiểm tra overdraw bằng Debug GPU Overview.
  2. Sử dụng công cụ Hierarchy Viewer để kiểm tra cấu trúc phân cấp View.
  3. Tối ưu hóa thời gian measure, layout, và draw bằng Hierarchy Viewer.

Bitmap pooling trong Android?
Bitmap pooling là kỹ thuật tái sử dụng bitmap thay vì tạo mới mỗi lần. Khi cần, kiểm tra stack bitmap xem có bitmap có sẵn không, nếu có thì tái sử dụng, nếu không thì tạo mới.

Sự khác biệt giữa commit() và apply() trong SharedPreferences?

  1. commit(): Ghi dữ liệu đồng bộ và trả về boolean.
  2. apply(): Ghi dữ liệu bất đồng bộ, không trả về giá trị, hiệu suất nhanh hơn vì lưu trữ bất đồng bộ.

Cách giảm dung lượng file APK trong Android.

  1. Bật Proguard.
  2. Bật shrinkResources.
  3. Loại bỏ tài nguyên không cần thiết trong resConfigs.
  4. Chuyển hình ảnh sang dạng webp hoặc vector drawable.

S.O.L.I.D principles trong phát triển phần mềm.

  1. Single Responsibility Principle (SRP)
  2. Open-Closed Principle (OCP)
  3. Liskov Substitution Principle (LSP)
  4. Interface Segregation Principle (ISP)
  5. Dependency Inversion Principle (DIP)