Android Framework
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
Phần tiêu đề “1. Context trong Android”Q: Context trong Android là gì? Có những loại Context nào?
Phần tiêu đề “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 objectsval appContext = applicationContext
// Activity Context - cho UI operationsval 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?
Phần tiêu đề “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 operationsval intent = Intent(this, DetailActivity::class.java)startActivity(intent)
// baseContext - cho custom ContextWrapperoverride 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
Phần tiêu đề “2. Application Class”Q: Application class là gì và khi nào nên sử dụng?
Phần tiêu đề “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()) } }}<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
Phần tiêu đề “3. AndroidManifest.xml”Q: Mục đích của file AndroidManifest.xml là gì?
Phần tiêu đề “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
Phần tiêu đề “4. Android Components”Q: Có bao nhiêu loại Android Components chính?
Phần tiêu đề “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 |
// Activityclass MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) }}
// Serviceclass 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 }}
// BroadcastReceiverclass 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
Phần tiêu đề “5. Activity vs Fragment”Q: Sự khác nhau giữa Activity và Fragment?
Phần tiêu đề “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 FragmentsupportFragmentManager.beginTransaction() .replace(R.id.container, HomeFragment()) .addToBackStack(null) .commit()📚 Tìm hiểu thêm: Fragments
6. Configuration Changes
Phần tiêu đề “6. Configuration Changes”Q: Điều gì xảy ra khi configuration change (xoay màn hình)?
Phần tiêu đề “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ị)
Phần tiêu đề “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
Phần tiêu đề “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)
Phần tiêu đề “3. rememberSaveable (Compose)”@Composablefun Counter() { var count by rememberSaveable { mutableStateOf(0) } Button(onClick = { count++ }) { Text("Count: $count") }}4. android:configChanges (Tránh dùng)
Phần tiêu đề “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
Phần tiêu đề “7. Memory Management”Q: Android quản lý memory như thế nào? Làm sao tránh memory leaks?
Phần tiêu đề “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 Activitycompanion object { var activity: Activity? = null // DON'T DO THIS}
// ✅ Use WeakReferenceclass 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 componentsviewLifecycleOwner.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)
Phần tiêu đề “8. ANR (Application Not Responding)”Q: ANR là gì? Nguyên nhân và cách phòng tránh?
Phần tiêu đề “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 Threadval data = api.fetchData() // Blocks UI
// ✅ Use CoroutinesviewModelScope.launch { val data = withContext(Dispatchers.IO) { api.fetchData() } updateUI(data)}
// ✅ Use WorkManager for persistent tasksval 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
Phần tiêu đề “9. Intents”Q: Explicit Intent vs Implicit Intent?
Phần tiêu đề “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 Activityval intent = Intent(this, DetailActivity::class.java).apply { putExtra("item_id", 123)}startActivity(intent)
// Implicit Intent - let system choose handlerval shareIntent = Intent(Intent.ACTION_SEND).apply { type = "text/plain" putExtra(Intent.EXTRA_TEXT, "Check this out!")}startActivity(Intent.createChooser(shareIntent, "Share via"))
// Open URLval webIntent = Intent(Intent.ACTION_VIEW, Uri.parse("https://google.com"))startActivity(webIntent)📚 Tìm hiểu thêm: Intents trong Android
10. Storage Options
Phần tiêu đề “10. Storage Options”Q: Các cách lưu trữ data trong Android?
Phần tiêu đề “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@Daointerface 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
Phần tiêu đề “11. SDK Versions trong build.gradle.kts”Q: targetSdk trong build.gradle.kts là gì? Khác gì với minSdk và compileSdk?
Phần tiêu đề “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 đó.
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?
Phần tiêu đề “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 permissionif (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:
Phần tiêu đề “Ví 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:
Phần tiêu đề “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
Phần tiêu đề “📝 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…”