Câu hỏi phỏng vấn Android cơ bản
Phần này tổng hợp các câu hỏi phỏng vấn phổ biến về Android Framework, dựa trên sách Manifest Android Interview của Jaewoong Eum.
1. Context trong Android
Q: Context trong Android là gì? Có những loại Context nào?
Trả lời:
Context là abstract class cung cấp access đến application resources, system services, và các operations như launching activities, broadcasting, receiving intents.
Các loại Context:
| Loại | Mô tả | Use Case |
|---|---|---|
| Application Context | Singleton, tồn tại suốt vòng đời app | Singletons, libraries initialization |
| Activity Context | Gắn với lifecycle của Activity | UI operations, dialogs, themes |
| Service Context | Gắn với lifecycle của Service | Background operations |
| Base Context | Context nền tảng của ContextWrapper | Custom ContextWrapper |
// Application Context - an toàn cho long-lived objects
val appContext = applicationContext
// Activity Context - cho UI operations
val dialog = AlertDialog.Builder(this) // 'this' là Activity
.setTitle("Example")
.show()⚠️ Quan trọng: Sử dụng
applicationContextcho objects tồn tại lâu dài để tránh memory leak. Chỉ dùng Activity context cho UI operations.
📚 Tìm hiểu thêm: Activity trong Android
Q: Sự khác nhau giữa this và baseContext trong Activity?
Trả lời:
this: Reference đến instance Activity hiện tại, bao gồm lifecycle và UI capabilitiesbaseContext: Context nền tảng mà Activity được xây dựng trên đó (từContextWrapper)
// this - cho UI operations
val intent = Intent(this, DetailActivity::class.java)
startActivity(intent)
// baseContext - cho custom ContextWrapper
override fun attachBaseContext(newBase: Context) {
super.attachBaseContext(CustomContextWrapper(newBase))
}Khi nào dùng:
this: Starting activities, showing dialogs, accessing resourcesbaseContext: Custom theming, locale changes, advanced wrapping
2. Application Class
Q: Application class là gì và khi nào nên sử dụng?
Trả lời:
Application class là base class duy trì global application state, được khởi tạo trước mọi components khác (Activities, Services, BroadcastReceivers).
Các methods quan trọng:
| Method | Mô tả |
|---|---|
onCreate() | Khởi tạo app-wide dependencies, chỉ gọi 1 lần |
onTerminate() | Chỉ gọi trong emulator, không dùng production |
onLowMemory() | Hệ thống thiếu memory |
onTrimMemory() | Memory state thay đổi, granular control |
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
// Initialize global dependencies
initTimber()
initAnalytics()
initDependencyInjection()
}
private fun initTimber() {
if (BuildConfig.DEBUG) {
Timber.plant(Timber.DebugTree())
}
}
}<!-- AndroidManifest.xml -->
<application
android:name=".MyApplication"
... >
</application>Best Practices:
- ✅ Initialize libraries (Timber, Firebase, Analytics)
- ✅ Setup dependency injection (Hilt, Koin)
- ❌ Avoid long-running tasks trong
onCreate() - ❌ Don’t store Activity references
3. AndroidManifest.xml
Q: Mục đích của file AndroidManifest.xml là gì?
Trả lời:
AndroidManifest.xml là file cấu hình bắt buộc, cung cấp thông tin về app cho Android OS:
-
Khai báo Components:
- Activities, Services, BroadcastReceivers, ContentProviders
-
Permissions:
- Quyền app cần (INTERNET, CAMERA, LOCATION)
- Quyền app cung cấp cho apps khác
-
Hardware/Software Features:
- Yêu cầu camera, GPS, sensors
-
App Metadata:
- Package name, version, icon, theme
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.app">
<!-- Permissions -->
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.CAMERA"/>
<!-- Hardware features -->
<uses-feature android:name="android.hardware.camera"
android:required="false"/>
<application
android:name=".MyApplication"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme">
<!-- Activities -->
<activity android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<!-- Services -->
<service android:name=".MyService"/>
</application>
</manifest>📚 Tìm hiểu thêm: AndroidManifest.xml
4. Android Components
Q: Có bao nhiêu loại Android Components chính?
Trả lời:
Có 4 loại Android Components:
| Component | Mô tả | Use Case |
|---|---|---|
| Activity | Màn hình UI, entry point cho user interaction | Login screen, Home screen |
| Service | Background tasks không có UI | Music playback, sync data |
| BroadcastReceiver | Nhận và xử lý system/app events | Battery low, network change |
| ContentProvider | Chia sẻ data giữa các apps | Contacts, Media files |
// Activity
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
}
// Service
class MusicService : Service() {
override fun onBind(intent: Intent?): IBinder? = null
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
// Play music in background
return START_STICKY
}
}
// BroadcastReceiver
class NetworkReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
// Handle network change
}
}📚 Tìm hiểu thêm: Services trong Android
5. Activity vs Fragment
Q: Sự khác nhau giữa Activity và Fragment?
Trả lời:
| Aspect | Activity | Fragment |
|---|---|---|
| Definition | Full-screen component | Reusable UI portion |
| Lifecycle | Independent | Depends on host Activity |
| Back Stack | Activity stack | Fragment back stack |
| Communication | Intents | ViewModel, interfaces |
| Resource | Heavyweight | Lightweight |
Khi nào dùng Fragment:
- ✅ Multi-pane layouts (tablet)
- ✅ Reusable UI components
- ✅ Navigation với Navigation Component
- ✅ Bottom navigation, tabs
// Adding Fragment
supportFragmentManager.beginTransaction()
.replace(R.id.container, HomeFragment())
.addToBackStack(null)
.commit()📚 Tìm hiểu thêm: Fragments
6. Configuration Changes
Q: Điều gì xảy ra khi configuration change (xoay màn hình)?
Trả lời:
Khi configuration change xảy ra (screen rotation, language change, keyboard availability), mặc định:
onPause()→onStop()→onSaveInstanceState()→onDestroy()onCreate()→onStart()→onRestoreInstanceState()→onResume()
Các cách xử lý:
1. ViewModel (Khuyến nghị)
class MainViewModel : ViewModel() {
private val _data = MutableLiveData<List<Item>>()
val data: LiveData<List<Item>> = _data
// Data survives configuration changes
}2. onSaveInstanceState
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
outState.putString("key", value)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
savedInstanceState?.getString("key")?.let { value = it }
}3. rememberSaveable (Compose)
@Composable
fun Counter() {
var count by rememberSaveable { mutableStateOf(0) }
Button(onClick = { count++ }) {
Text("Count: $count")
}
}4. android:configChanges (Tránh dùng)
<activity android:name=".MainActivity"
android:configChanges="orientation|screenSize"/>📚 Tìm hiểu thêm: ViewModel, Compose State
7. Memory Management
Q: Android quản lý memory như thế nào? Làm sao tránh memory leaks?
Trả lời:
Android sử dụng Garbage Collection tự động thu hồi memory không sử dụng. Khi memory thấp, Low Memory Killer sẽ terminate background processes.
Nguyên nhân Memory Leaks:
| Nguyên nhân | Giải pháp |
|---|---|
| Static reference to Context | Dùng applicationContext |
| Long-lived listeners | Unregister trong onDestroy() |
| Inner class giữ outer reference | Dùng WeakReference hoặc static class |
| Handler/Runnable | Remove callbacks trong onDestroy() |
Best Practices:
// ❌ Memory leak - static reference to Activity
companion object {
var activity: Activity? = null // DON'T DO THIS
}
// ✅ Use WeakReference
class MyHandler(activity: Activity) : Handler(Looper.getMainLooper()) {
private val activityRef = WeakReference(activity)
override fun handleMessage(msg: Message) {
activityRef.get()?.let { activity ->
// Safe to use
}
}
}
// ✅ Use lifecycle-aware components
viewLifecycleOwner.lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.data.collect { updateUI(it) }
}
}Tools phát hiện leaks:
- LeakCanary
- Android Studio Memory Profiler
8. ANR (Application Not Responding)
Q: ANR là gì? Nguyên nhân và cách phòng tránh?
Trả lời:
ANR xảy ra khi Main Thread bị block hơn 5 giây, khiến app không phản hồi.
Nguyên nhân:
- Heavy computation trên Main Thread
- Synchronous network/database operations
- Blocking I/O operations
- Long loops,
Thread.sleep()
Cách phòng tránh:
// ❌ ANR - Network trên Main Thread
val data = api.fetchData() // Blocks UI
// ✅ Use Coroutines
viewModelScope.launch {
val data = withContext(Dispatchers.IO) {
api.fetchData()
}
updateUI(data)
}
// ✅ Use WorkManager for persistent tasks
val request = OneTimeWorkRequestBuilder<SyncWorker>().build()
WorkManager.getInstance(context).enqueue(request)Tools monitoring:
- Android Studio Profiler
- StrictMode
- ANR traces in
/data/anr/
📚 Tìm hiểu thêm: Coroutines, WorkManager
9. Intents
Q: Explicit Intent vs Implicit Intent?
Trả lời:
| Type | Mô tả | Use Case |
|---|---|---|
| Explicit | Chỉ định component cụ thể | Navigate trong app |
| Implicit | Khai báo action, system chọn | Share, open URL |
// Explicit Intent - navigate to specific Activity
val intent = Intent(this, DetailActivity::class.java).apply {
putExtra("item_id", 123)
}
startActivity(intent)
// Implicit Intent - let system choose handler
val shareIntent = Intent(Intent.ACTION_SEND).apply {
type = "text/plain"
putExtra(Intent.EXTRA_TEXT, "Check this out!")
}
startActivity(Intent.createChooser(shareIntent, "Share via"))
// Open URL
val webIntent = Intent(Intent.ACTION_VIEW, Uri.parse("https://google.com"))
startActivity(webIntent)📚 Tìm hiểu thêm: Intents trong Android
10. Storage Options
Q: Các cách lưu trữ data trong Android?
Trả lời:
| Storage | Use Case | Persist | Shared |
|---|---|---|---|
| SharedPreferences | Simple key-value settings | ✅ | ❌ |
| DataStore | Modern replacement for SharedPreferences | ✅ | ❌ |
| Room Database | Structured data, complex queries | ✅ | ❌ |
| Internal Storage | Private files | ✅ | ❌ |
| External Storage | Public files (photos, downloads) | ✅ | ✅ |
| Network/Cloud | Remote data synchronization | ✅ | ✅ |
// DataStore (Recommended)
val dataStore = context.createDataStore("settings")
dataStore.edit { prefs ->
prefs[THEME_KEY] = "dark"
}
// Room Database
@Dao
interface UserDao {
@Query("SELECT * FROM users")
fun getAll(): Flow<List<User>>
@Insert
suspend fun insert(user: User)
}📚 Tìm hiểu thêm: DataStore, Room Database, SharedPreferences
11. SDK Versions trong build.gradle.kts
Q: targetSdk trong build.gradle.kts là gì? Khác gì với minSdk và compileSdk?
Trả lời:
targetSdk là API level mà app được thiết kế và đã test để chạy. Nó cho biết app hỗ trợ đầy đủ các behaviors và features của Android version đó.
// build.gradle.kts
android {
namespace = "com.example.app"
compileSdk = 35 // API level để compile code
defaultConfig {
applicationId = "com.example.app"
minSdk = 24 // Android 7.0 - version thấp nhất hỗ trợ
targetSdk = 35 // Android 15 - version app được tối ưu cho
versionCode = 1
versionName = "1.0"
}
}So sánh 3 loại SDK:
| Property | Ý nghĩa | Ảnh hưởng |
|---|---|---|
| minSdk | Android version thấp nhất app có thể cài | Quyết định tập user có thể sử dụng app |
| compileSdk | API level để compile code | Cho phép sử dụng APIs mới nhất khi coding |
| targetSdk | API level app đã test và tối ưu | Quyết định behaviors của app trên devices mới |
Tại sao targetSdk quan trọng?
1. Android Behaviors thay đổi theo targetSdk:
// Nếu targetSdk >= 31 (Android 12)
// - Phải khai báo android:exported cho Activities
// - Approximate location permission xuất hiện
// - PendingIntent yêu cầu mutability flag
// Nếu targetSdk >= 33 (Android 13)
// - POST_NOTIFICATIONS permission bắt buộc request runtime
// - Photo picker thay thế storage permissions
// Ví dụ: Request notification permission
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
requestPermissions(arrayOf(Manifest.permission.POST_NOTIFICATIONS), 1)
}2. Forward Compatibility:
Khi device chạy Android cao hơn targetSdk, hệ thống sẽ chạy compatibility mode để đảm bảo app hoạt động như cũ:
// App với targetSdk = 30 chạy trên Android 14:
// - Không bị ảnh hưởng bởi các restrictions mới của Android 14
// - System "giả lập" behavior của Android 11 cho app3. Google Play Store Requirements:
// Yêu cầu hiện tại của Google Play:
// - New apps: targetSdk phải >= 34 (Android 14)
// - App updates: targetSdk phải >= 34
// Nếu không cập nhật targetSdk:
// - App bị ẩn khỏi users có device mới
// - App có thể bị xóa khỏi Play StoreVí dụ thực tế - Permission Changes:
// targetSdk = 22: Tất cả permissions cấp lúc install
// targetSdk >= 23: Runtime permissions
fun checkCameraPermission() {
// Với targetSdk >= 23, phải request runtime
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(
this,
arrayOf(Manifest.permission.CAMERA),
CAMERA_REQUEST_CODE
)
} else {
openCamera()
}
}Best Practices:
| ✅ Nên làm | ❌ Tránh |
|---|---|
| Giữ targetSdk cập nhật để tận dụng features mới | Để targetSdk quá cũ gây compatibility issues |
| Test kỹ trên API level = targetSdk | Nâng targetSdk mà không test |
| Đọc Android Migration Guides khi nâng version | Bỏ qua behavior changes documentation |
| Sử dụng AndroidX compatibility libraries | Hard-code version checks |
⚠️ Quan trọng: Khi nâng targetSdk, đọc kỹ Behavior Changes của version mới. Mỗi Android version có breaking changes khác nhau.
📝 Tips trả lời phỏng vấn
- Trả lời có cấu trúc: Definition → Explanation → Example → Best Practice
- Luôn cho ví dụ code khi có thể
- Đề cập trade-offs và khi nào không nên dùng
- Kết nối với kinh nghiệm thực tế nếu có
- Nếu không biết: “I’m not sure, but I would approach it by…”