Tổng hợp 71 câu hỏi phỏng vấn Android kèm đáp án chi tiết, song ngữ Việt–Anh — sắp xếp từ cơ bản đến nâng cao. Ôn luyện miễn phí, tự động lưu tiến độ.
val khai báo biến chỉ đọc, không thể gán lại sau khi khởi tạo (tương tự final trong Java), còn var khai báo biến có thể thay đổi giá trị. Dùng val làm mặc định giúp code an toàn hơn và phù hợp với nguyên…
Trong Kotlin, biến mặc định không được phép null để loại bỏ NullPointerException. Muốn cho phép null, bạn khai báo kiểu nullable bằng ? (ví dụ String?). Compiler bắt buộc bạn xử lý null ngay lúc biên dịch qua các toán tử như ?. (safe…
Extension function cho phép bạn thêm method mới vào class có sẵn mà không cần kế thừa hay sửa code gốc. Ví dụ có thể thêm method thẳng vào class String: fun String.isPhoneNumber(): Boolean { return this.length == 10 }. Trước tên hàm là tên…
Data class tự động sinh ra các method boilerplate như equals(), hashCode(), toString() và copy(). Data class cần ít nhất một tham số trong constructor và rất phù hợp để chứa dữ liệu (như response API hay model database). Chúng không thể là abstract, open,…
Sealed class giới hạn một class hierarchy thành tập hợp subclass cố định, được định nghĩa trong cùng một file hoặc package. Rất phù hợp để biểu diễn các trạng thái giới hạn như response API (Success/Error/Loading). Khi dùng với when, compiler bắt buộc xử…
Scope function thực thi một block code trên một object trong một scope tạm thời. let chạy code chỉ khi object khác null (trả về kết quả lambda). run giống let nhưng dùng this thay vì tham số. apply cấu hình object và trả về…
Coroutine là các hàm nhẹ có thể tạm dừng và tiếp tục, cho phép lập trình bất đồng bộ hiệu quả mà không block thread. Khác với callback dễ dẫn đến "callback hell", coroutine cho phép viết code bất đồng bộ trông như code tuần…
launch là coroutine fire-and-forget, trả về Job và không trả về kết quả. async dùng khi cần thực hiện tác vụ và lấy kết quả về, trả về Deferred. Dùng launch cho tác vụ độc lập (như cập nhật UI), còn async khi cần kết…
Suspend function là hàm có thể tạm dừng mà không chặn thread, rồi chạy tiếp khi có kết quả. Nó chỉ gọi được từ một coroutine hoặc từ một suspend function khác. Cơ chế: compiler biến hàm suspend thành hàm nhận thêm một tham số…
Bạn có thể dùng try-catch thông thường bên trong coroutine để xử lý exception cục bộ. Với exception không được bắt, dùng CoroutineExceptionHandler để bắt ở cấp coroutine scope. viewModelScope dùng SupervisorJob nên coroutine con thất bại không huỷ coroutine anh em, nhưng exception không…
Companion object cho phép định nghĩa các thành viên kiểu static (hằng số, factory method) bên trong class, thuộc về class chứ không phải instance. Mỗi class chỉ có một companion object. Có thể gọi trực tiếp mà không cần tạo instance: MyClass.myStaticMethod(). Giống static…
Destructuring cho phép bạn tách một object thành các biến riêng lẻ trong một câu lệnh duy nhất. Ví dụ val (name, age) = person trích xuất thuộc tính từ data class. Cũng có thể dùng trong vòng lặp: for ((key, value) in map). Hoạt…
Activity lifecycle là chuỗi callback hệ thống gọi khi một màn hình được tạo, hiện ra, mất focus, bị che và bị huỷ: - onCreate(): khởi tạo một lần — setContent/setContentView, lấy ViewModel, đọc savedInstanceState. - onStart(): Activity hiện ra (visible). - onResume(): ở foreground…
replace() xoá Fragment hiện tại và thêm Fragment mới vào chỗ đó — khi back thì Fragment bị replace sẽ được tạo lại. add() giữ Fragment hiện có và chồng Fragment mới lên trên — khi back thì quay về Fragment cũ. Dùng replace() để…
Intent là object "yêu cầu" gửi cho hệ thống để khởi động một component: mở Activity, chạy Service, gửi broadcast. Có hai loại: - Explicit intent: chỉ rõ component đích — thường dùng trong nội bộ app. - Implicit intent: chỉ khai báo hành động…
Service là component chạy việc không cần UI. Nó chạy trên main thread của process, nên việc nặng vẫn phải tự đẩy sang coroutine hoặc thread khác. Ba dạng: - Started service (startService): chạy đến khi tự stopSelf() hoặc bị dừng. - Foreground service: bắt…
BroadcastReceiver là component lắng nghe các broadcast trong toàn hệ thống (như pin yếu, thay đổi network, hay broadcast tuỳ chỉnh). Bạn đăng ký nó trong manifest (static) hoặc trong code (dynamic), và nó kích hoạt onReceive() khi nhận được broadcast phù hợp. Tránh thực…
ContentProvider là lớp trừu tượng cung cấp quyền truy cập có kiểm soát vào dữ liệu của app cho các app hoặc process khác. Nó dùng URI để xác định resource và implement các thao tác CRUD qua query(), insert(), update(), delete(). Danh bạ, lịch,…
Android chia permission theo mức rủi ro: - Normal (INTERNET, VIBRATE): khai báo trong manifest là được cấp khi cài. - Dangerous / runtime (camera, vị trí, danh bạ, micro, POSTNOTIFICATIONS từ Android 13): từ Android 6.0 (API 23) phải xin lúc chạy; người dùng…
onSaveInstanceState() là callback để lưu trạng thái UI tạm thời (như vị trí scroll) trước khi activity bị destroy do configuration change. Bundle này được truyền vào onCreate() hoặc onRestoreInstanceState(). Khác với lưu trữ lâu dài như SharedPreferences hay database. Dùng nó cho trạng thái…
Intent filter được khai báo trong manifest để chỉ định loại implicit intent mà Activity có thể xử lý. Chúng định nghĩa action, category, và kiểu dữ liệu. Khi bạn gửi implicit intent, hệ thống tìm tất cả app có Intent filter phù hợp. Ví…
Process là một instance riêng biệt của app với bộ nhớ và tài nguyên riêng, chạy độc lập với các process khác. Thread là đơn vị thực thi nhẹ hơn trong một process, chia sẻ bộ nhớ với các thread khác. Android app có main…
Jetpack Compose là bộ công cụ UI declarative hiện đại cho phép xây dựng giao diện Android bằng Kotlin function thay vì XML. Nó đang thay thế XML vì code ngắn gọn hơn, type-safe, và dễ tái sử dụng hơn. Compose tự động cập nhật…
@Composable đánh dấu một Kotlin function là pure, idempotent (cùng input → cùng output), và được gọi bởi Compose runtime chứ không phải do bạn gọi thủ công — đây là ràng buộc quan trọng nhất. Function phải trả về Unit, không có side effect…
mutableStateOf() tạo một MutableState<T mà Compose theo dõi được: composable nào đọc .value sẽ được recompose khi giá trị đổi. remember giữ object đó qua các lần recomposition — thiếu remember, mỗi lần recompose lại tạo state mới về giá trị ban đầu. Các biến…
remember giữ state qua các lần recomposition trong scope của composable nhưng mất khi configuration change như xoay màn hình. rememberSaveable persist state qua configuration change bằng cách tự động lưu vào Bundle. Dùng rememberSaveable cho dữ liệu người dùng nhập (form fields) và remember…
State hoisting nghĩa là chuyển state từ composable con lên composable cha, làm cho composable con trở nên stateless. Composable stateless nhận state qua tham số và callback để cập nhật state, giúp tái sử dụng trên nhiều màn hình. Ví dụ hoist state của…
LaunchedEffect là side-effect function khởi chạy một coroutine scope gắn với lifecycle của composable. Dùng cho các tác vụ một lần như load data, animation, hay analytics. Nó chạy khi key parameter thay đổi và huỷ khi composable rời khỏi composition. Ví dụ: LaunchedEffect(userId) {…
Modifier là object có thể chain lại để thêm behavior, styling, hay layout cho composable. Ví dụ: .size(100.dp), .background(Color.Blue), .padding(16.dp), .clickable { }, .weight(1f). Thứ tự quan trọng vì modifier chain từ trái sang phải: .padding().background() khác với .background().padding(). Modifier là ví dụ điển hình…
Dùng Compose Navigation library với NavController và NavHost. Định nghĩa NavGraph với các màn hình và route, rồi dùng navController.navigate(route) để điều hướng. State được giữ lại khi quay về màn hình trước. Với Compose Navigation 2.8+ (stable từ Oct 2024), dùng type-safe routes qua…
Dùng MaterialTheme (Material 3) hoặc CompositionLocal tuỳ chỉnh để tập trung hoá các thuộc tính theme. Định nghĩa màu sắc, typography, và shape trong theme object, dùng CompositionLocalProvider để cung cấp chúng cho cây composable. Wrap app trong MaterialTheme(colorScheme = colorScheme, typography = typography) {…
MVVM (Model-View-ViewModel) tách UI logic khỏi business logic: Model chứa dữ liệu và business rule, View hiển thị UI (Activity/Fragment/Composable), ViewModel chứa UI state và logic, tồn tại qua configuration change. ViewModel expose LiveData/StateFlow để View observe. Sự tách biệt này cải thiện khả năng…
Repository pattern trừu tượng hoá các nguồn dữ liệu (local database, remote API, cache) sau một interface duy nhất, để ViewModel không cần biết dữ liệu đến từ đâu. Sự decoupling này giúp test dễ hơn (mock repository) và cho phép đổi nguồn dữ liệu…
Cả hai đều giữ giá trị hiện tại và báo cho observer khi giá trị đổi, nhưng khác gốc: LiveData là class của Android, lifecycle-aware sẵn; StateFlow thuộc Kotlin coroutines, không phụ thuộc Android. LiveData StateFlow --------- Giá trị ban đầu Không bắt buộc (có…
ViewModel là state holder của một màn hình: giữ và chuẩn bị dữ liệu cho UI, và sống qua configuration change (xoay màn hình, đổi dark mode) — Activity bị tạo lại nhưng ViewModel vẫn còn, không phải gọi API lại. Vai trò đúng theo…
Dependency injection nghĩa là cung cấp dependency của một object qua tham số thay vì object tự tạo bên trong. Lợi ích: test dễ hơn (truyền mock dependency), loose coupling, linh hoạt khi đổi implementation. Ví dụ: thay vì val database = Database.getInstance() bên trong…
Hilt là thư viện DI được xây trên Dagger, thiết kế riêng cho Android. Nó loại bỏ boilerplate bằng cách cung cấp module có sẵn cho Android component. Đánh dấu Application với @HiltAndroidApp, Activity/Fragment với @AndroidEntryPoint, và inject bằng @Inject. Hilt tự động quản lý…
Hilt scope kiểm soát thời gian sống của dependency instance: @Singleton sống suốt vòng đời app, @ActivityScoped theo vòng đời Activity, @ViewModelScoped theo ViewModel, và @FragmentScoped theo Fragment. Scope mặc định là unscoped (tạo instance mới mỗi lần). Chọn scope dựa vào thời gian muốn…
Room là thư viện Jetpack bọc SQLite: bạn khai báo entity và câu query bằng annotation, Room sinh code lúc compile (qua KSP) và kiểm tra câu SQL ngay lúc build. So với dùng SQLiteOpenHelper trực tiếp: - Sai tên cột hay cú pháp SQL…
DAO là interface với các method cho thao tác CRUD trên database. Bạn annotate method với @Query, @Insert, @Update, @Delete. Room sinh implementation lúc compile. Ví dụ: @Query("SELECT FROM users WHERE id = :id") suspend fun getUser(id: Int): User. DAO là nơi định nghĩa query,…
Retrofit là HTTP client type-safe chuyển REST API thành Kotlin interface. Bạn định nghĩa interface với method được annotate bằng HTTP verb như @GET, @POST, thêm kiểu request/response, và Retrofit tự sinh implementation. Nó tự động deserialize JSON response thành Kotlin object, xử lý header,…
Interceptor chặn HTTP request/response để chỉnh sửa chúng. - Application interceptor chạy một lần cho mỗi request; network interceptor chạy cho từng lần gọi network thực tế (kể cả redirect và retry). - Dùng phổ biến: gắn auth header, log request/response, xử lý refresh token,…
Dùng Interceptor để thêm auth header vào mọi request. Khi token hết hạn, interface Authenticator xử lý token refresh bằng cách chặn response 401 và retry với token mới. Lưu token an toàn trong EncryptedSharedPreferences. Gửi token trong Authorization header: Authorization: Bearer token. Xử lý…
DataStore là bản thay thế hiện đại cho SharedPreferences, được xây dựng trên coroutine và Flow cho lưu trữ dữ liệu type-safe và transactional. Async-first (không blocking), hỗ trợ protocol buffer cho type safety, và an toàn hơn SharedPreferences vốn có vấn đề threading. Dùng…
WorkManager lên lịch background work có thể defer được, tồn tại qua app restart và system reboot. Nó tự động xử lý Doze Mode và App Standby, chọn cơ chế scheduling tốt nhất (JobScheduler, BroadcastReceiver). Dùng cho tác vụ không gấp nhưng phải chắc chắn…
Paging 3 là thư viện phân trang được khuyến nghị, load hiệu quả dataset lớn từ nguồn local/remote. Bạn tạo PagingSource (hoặc RemoteMediator cho network+database), dùng Pager để tạo paginated stream, và collect PagingData trong UI với collectAsLazyPagingItems(). Nó xử lý tự động loading, appending,…
Observer pattern cho phép các object (observer) đăng ký nhận thông báo về thay đổi trạng thái của object khác (subject). Trong Android, LiveData/StateFlow là các implementation của pattern này. Khi bạn gọi observe() hoặc collect(), bạn đang đăng ký làm observer. Khi dữ liệu…
Configuration change destroy và recreate Activity/Fragment. Bảo toàn state bằng: SavedInstanceState (UI state tạm thời), ViewModel (logic và data), và SharedPreferences/DataStore (data lâu dài). Không nên dùng android:configChanges để tắt recreation trừ khi thực sự cần thiết. Trong Compose, state tự động tồn tại qua…
Context là cầu nối tới tài nguyên và dịch vụ hệ thống: truy cập resources, khởi động Activity/Service, lấy getSystemService(), mở database... Về vòng đời có hai loại chính: - Activity context: gắn với vòng đời một Activity, biết về theme/UI. Dùng khi cần theme…
ANR là hộp thoại hệ thống hiện ra khi main thread (UI thread) bị chặn quá lâu nên app không phản hồi. Các ngưỡng chính: - Không xử lý input event (chạm, phím) trong 5 giây. - BroadcastReceiver.onReceive() chạy quá lâu (10 giây foreground, 60…
RecyclerView là widget hiển thị danh sách/lưới lớn hiệu quả bằng cách tái sử dụng một số ít View thay vì tạo View cho mọi item. Hình dung một cửa sổ chỉ thấy vài dòng: khi cuộn, dòng trôi khỏi màn hình không bị huỷ…
Gradle là hệ thống build tự động mà Android dùng để biên dịch mã, gói tài nguyên, và tạo ra file APK/AAB. Android Gradle Plugin (AGP) mở rộng Gradle với các tác vụ riêng cho Android. Vai trò chính: - Quản lý dependency: khai báo…