Phỏng vấn vị trí lập trình viên Android Kotlin


Chào bạn, dưới đây là bộ 50 câu hỏi phỏng vấn Android (Kotlin) từ cơ bản đến nâng cao, được biên soạn kỹ lưỡng kèm giải thích chi tiết và code demo để bạn chuẩn bị tốt nhất cho buổi phỏng vấn.


  • Lời giải: val (value) là biến chỉ đọc (read-only), tương đương với final trong Java. Một khi đã gán giá trị thì không thể thay đổi. var (variable) là biến có thể thay đổi giá trị (mutable).

  • Code demo:

Kotlin
val name = "Android" // Không thể gán lại
var version = 13
version = 14 // Hợp lệ
  • Lời giải: Kotlin phân biệt rõ ràng giữa kiểu dữ liệu có thể null (String?) và không thể null (String). Điều này giúp tránh lỗi NullPointerException (NPE) ngay từ khi biên dịch.

  • Code demo:

Kotlin
var a: String = "abc" // Không thể gán null
var b: String? = "abc" // Có thể gán null
b = null 
println(b?.length) // Safe call: trả về null nếu b là null
  • Lời giải: lateinit dùng cho var, cho phép khởi tạo biến sau (thường dùng trong Dependency Injection hoặc onCreate). lazy dùng cho val, giá trị chỉ được tính toán trong lần đầu tiên truy cập.

  • Code demo:

Kotlin
lateinit var userRepository: UserRepository

val database: Database by lazy { 
    Database.getInstance() 
}
  • Lời giải: Là lớp chuyên dùng để chứa dữ liệu. Trình biên dịch sẽ tự động tạo các hàm equals(), hashCode(), toString(), và copy().

  • Code demo:

Kotlin
data class User(val id: Int, val name: String)
  • Lời giải: Kotlin không có từ khóa static. companion object được dùng để định nghĩa các thành viên thuộc về lớp chứ không phải instance của lớp.

  • Code demo:

Kotlin
class Config {
    companion object {
        const val BASE_URL = "https://api.example.com"
    }
}
  • Lời giải: List là interface chỉ đọc (không có hàm add hoặc remove). MutableList cho phép sửa đổi các phần tử bên trong.

  • Code demo:

Kotlin
val list = listOf(1, 2) // Immutable
val mList = mutableListOf(1, 2)
mList.add(3)
  • Lời giải: Cho phép thêm chức năng mới vào một lớp có sẵn mà không cần kế thừa lớp đó.

  • Code demo:

Kotlin
fun String.isEmail(): Boolean = this.contains("@")
val email = "test@gmail.com"
println(email.isEmail())
  • Lời giải: Là lớp dùng để biểu diễn một hệ thống phân cấp lớp bị hạn chế. Các subclass phải được định nghĩa trong cùng một file. Thường dùng cho State Management (Success, Error, Loading).

  • Code demo:

Kotlin
sealed class Result {
    data class Success(val data: String) : Result()
    object Loading : Result()
}
  • Lời giải: Là hàm nhận một hàm khác làm tham số hoặc trả về một hàm.

  • Code demo:

Kotlin
fun operate(a: Int, b: Int, action: (Int, Int) -> Int): Int {
    return action(a, b)
}
  • Lời giải: Các hàm này thực thi một khối code trên một đối tượng. Khác nhau ở giá trị trả về và cách tham chiếu đối tượng (it hoặc this).

  • Code demo:

Kotlin
val person = Person().apply { name = "Diep" } // Trả về chính object
val length = person.let { it.name.length } // Trả về kết quả lambda
  • Lời giải: Là một giải pháp quản lý luồng nhẹ (lightweight threads), giúp xử lý các tác vụ bất đồng bộ (API call, Database) mà không làm treo UI.

  • Code demo:

Kotlin
viewModelScope.launch {
    val data = repository.getData() // suspend function
}
  • Lời giải: Là hàm có thể tạm dừng việc thực thi mà không làm chặn luồng hiện tại, sau đó tiếp tục khi dữ liệu đã sẵn sàng. Chỉ gọi được từ coroutine hoặc suspend function khác.

  • Code demo:

Kotlin
suspend fun fetchUser(): User = withContext(Dispatchers.IO) { ... }
  • Lời giải: Main: Chạy trên UI thread. IO: Dành cho các tác vụ nhập xuất (mạng, file). Default: Cho các tác vụ tốn CPU (sắp xếp list, xử lý ảnh).

  • Code demo:

Kotlin
launch(Dispatchers.IO) { /* call API */ }
  • Lời giải: onCreate(), onStart(), onResume(), onPause(), onStop(), onDestroy(), onRestart().

  • Lời giải: onStart() khi Activity bắt đầu hiển thị với người dùng. onResume() khi Activity sẵn sàng tương tác (có focus).

  • Lời giải: Lưu trữ và quản lý dữ liệu liên quan đến UI theo vòng đời. Nó giúp dữ liệu không bị mất khi cấu hình thay đổi (như xoay màn hình).

  • Lời giải: LiveData thuộc Android, nhận biết vòng đời (Lifecycle-aware). StateFlow thuộc Kotlin Coroutines, mạnh mẽ hơn nhưng cần xử lý vòng đời thủ công qua repeatOnLifecycle.

  • Lời giải: Có thêm các hàm như onAttach(), onCreateView(), onDestroyView(), onDetach().

  • Lời giải: Dùng Shared ViewModel (khuyên dùng), Bundle (Arguments), hoặc Fragment Result API.

  • Lời giải: Là interface chứa thông tin về môi trường ứng dụng, cho phép truy cập tài nguyên (Resources), khởi chạy Activity, v.v. Có ApplicationContextActivityContext.

  • Lời giải: Explicit: Chỉ rõ component sẽ chạy (ví dụ DetailActivity::class.java). Implicit: Chỉ nêu hành động (ví dụ ACTION_VIEW để mở browser).

  • Lời giải: Tối ưu hóa việc hiển thị danh sách lớn bằng cách tái sử dụng (recycle) các view cũ thay vì tạo mới liên tục. Cần AdapterViewHolder.

  • Lời giải: Là tiện ích giúp RecyclerView tính toán sự khác biệt giữa danh sách cũ và mới để cập nhật chính xác những phần tử thay đổi, thay vì gọi notifyDataSetChanged().

  • Lời giải: Giúp tạo giao diện phức tạp với cấu trúc phẳng (flat hierarchy), giảm độ sâu của view tree, từ đó tăng hiệu năng render.

  • Lời giải: View Binding chỉ thay thế findViewById. Data Binding cho phép gán dữ liệu trực tiếp vào XML.

  • Lời giải: Kỹ thuật cung cấp các object mà một class cần từ bên ngoài thay vì để class đó tự tạo. Giúp code dễ test và bảo trì (ví dụ: Hilt, Koin).

  • Lời giải: Là thư viện DI chuẩn cho Android được Google khuyên dùng, xây dựng dựa trên Dagger nhưng đơn giản hơn nhiều.

  • Lời giải: Thư viện Type-safe HTTP client dùng để gọi API, chuyển đổi JSON sang object một cách tự động.

  • Lời giải: Là một lớp trừu tượng nằm trên SQLite, giúp quản lý database cục bộ dễ dàng hơn với các annotation @Entity, @Dao, @Database.

  • Lời giải: Dùng Coroutines (khuyên dùng hiện nay), Thread/Handler, hoặc RxJava.

  • Lời giải: Dùng để chạy các tác vụ nền (background tasks) ngay cả khi app bị đóng hoặc thiết bị khởi động lại, đảm bảo tác vụ sẽ được thực thi.

  • Lời giải: Component chạy ngầm không có UI. Có 2 loại: Started ServiceBound Service. Lưu ý Foreground Service yêu cầu notification.

  • Lời giải: Giúp ứng dụng lắng nghe các sự kiện từ hệ thống (Pin yếu, mất mạng) hoặc từ ứng dụng khác.

  • Lời giải: Quản lý việc truy cập vào tập dữ liệu có cấu trúc và chia sẻ dữ liệu giữa các ứng dụng khác nhau (ví dụ: truy cập Danh bạ).

  • Lời giải: launch dùng cho tác vụ "fire and forget", không trả về giá trị. async trả về một Deferred và bạn dùng await() để lấy kết quả.

  • Lời giải: 5 nguyên tắc thiết kế phần mềm giúp code linh hoạt hơn: Single Responsibility, Open/Closed, Liskov Substitution, Interface Segregation, Dependency Inversion.

  • Lời giải: Model-View-ViewModel. Tách biệt logic xử lý dữ liệu (Model), logic giao diện (ViewModel) và hiển thị (View/Activity).

  • Lời giải: Framework hiện đại để xây dựng giao diện Android theo phong cách Declarative (khai báo), sử dụng hoàn toàn bằng Kotlin thay vì XML.

  • Lời giải: Là quá trình gọi lại các hàm Composable khi dữ liệu đầu vào (State) thay đổi để cập nhật UI.

  • Lời giải: mutableStateOf dùng để giữ giá trị, remember giúp lưu trữ giá trị đó qua các lần Recomposition.

  • Lời giải: Thư viện giúp quản lý việc chuyển màn hình, truyền dữ liệu và quản lý Backstack một cách đồng nhất.

  • Lời giải: Không lưu context của Activity trong biến static, hủy đăng ký Listener/Observer trong onDestroy(), dùng WeakReference khi cần.

  • Lời giải: Lỗi xảy ra khi Main Thread bị chặn quá lâu (thường > 5 giây) do xử lý tác vụ nặng.

  • Lời giải: DataStore là giải pháp mới thay thế SharedPreferences, hỗ trợ Coroutines, xử lý lỗi tốt hơn và chạy bất đồng bộ hoàn toàn.

  • Lời giải: Sử dụng Proguard/R8, dùng định dạng ảnh WebP, xóa tài nguyên không dùng (Lint), sử dụng Android App Bundle (.aab).

  • Lời giải: == kiểm tra giá trị (gọi hàm equals()), === kiểm tra tham chiếu (hai biến có trỏ cùng một vùng nhớ không).

  • Lời giải: Khi dùng từ khóa inline, trình biên dịch sẽ copy code của hàm đó vào nơi gọi, giúp giảm chi phí cấp phát bộ nhớ cho lambda expression.

  • Lời giải: Là luồng dữ liệu lạnh (cold stream), phát ra nhiều giá trị theo thời gian và kết thúc thành công hoặc có lỗi.

  • Lời giải: Một thư viện Dependency Injection nhẹ cho Kotlin, sử dụng DSL (Domain Specific Language) thay vì code generation như Hilt.

  • Lời giải: Gradle là hệ thống build tự động, giúp quản lý thư viện (dependencies), định dạng cấu hình build (build types, flavors) và tự động hóa quy trình đóng gói ứng dụng.

Phản hồi từ học viên

5

Tổng 0 đánh giá
Developer Toolbox

TEXT CASE

FORMAT & CLEAN

ENCODE & DECODE

JSON & CRYPTO

Đã sao chép!!!
Gozic - Hệ thống học lập trình, luyện thi, kiểm tra trắc nghiệm trực tuyến uy tín tại Việt Nam.
Hotline: 0967025996
Gozic - Hệ thống học lập trình, luyện thi, kiểm tra trắc nghiệm trực tuyến uy tín tại Việt Nam.