Table of Contents
- Activities
- Fragments
- Services
- Broadcast Receivers
- Content Providers
- UI Design
- Data Storage
- Networking
- Concurrency
- Dependency Injection
- Testing
- Performance Optimization
- Security
- Jetpack Libraries
Advanced Android Interview Guide
Deep Technical Breakdown for Senior Engineers
1. Activities
🔄 Lifecycle Deep Dive
class Activity : ComponentActivity() {
// Creation Phase
override fun onCreate() { /* Initialize UI, bind ViewModel */ }
override fun onStart() { /* Visible but not interactive (e.g., behind dialog) */ }
override fun onResume() { /* Interactive state - start animations/sensors */ }
// Destruction Phase
override fun onPause() { /* Release exclusive resources (e.g., camera) */ }
override fun onStop() { /* Heavy cleanup (DB connections) */ }
override fun onDestroy() { /* Final cleanup (unregister receivers) */ }
// Configuration Changes
override fun onSaveInstanceState(bundle: Bundle) { /* Save transient UI state */ }
override fun onRestoreInstanceState(bundle: Bundle) { /* Restore UI state */ }
}
Flowchart:
onCreate() → onStart() → onResume() → [Running]
↑ | |
└── onRestart() ← onStop() ← onPause()
|
└── onDestroy()
🎯 Launch Modes & Intent Flags
singleTop
: Reuse existing instance if it’s at the top of the stack.intent.flags = Intent.FLAG_ACTIVITY_SINGLE_TOP
- **
singleTask**
: Creates a new task and becomes the root.<activity android:launchMode="singleTask" />
- **
FLAG_ACTIVITY_CLEAR_TOP**
: Destroys all activities above the target in the stack.
Interview Q:
Q: What happens if Activity A (launchMode=singleTask) starts Activity B, which starts Activity A again?
A: A’s existing instance is brought to the front. The back stack becomes: A (root) → B → A (top).
2. Fragments
🧩 Lifecycle & Back Stack
Lifecycle Methods:
onAttach() → onCreate() → onCreateView() → onViewCreated() → onStart() → onResume()
onPause() → onStop() → onDestroyView() → onDestroy() → onDetach()
Back Stack Behavior:
addToBackStack("tag")
: Saves fragment state. Popping usespopBackStackImmediate("tag", POP_BACK_STACK_INCLUSIVE)
.- FragmentStateAdapter vs FragmentPagerAdapter:
- StateAdapter: Destroys non-adjacent fragments (better for memory).
- PagerAdapter: Keeps fragments in memory (faster tab switching).
Interview Q:
Q: Why does onDestroyView()
get called during a fragment transaction?
A: The fragment’s view hierarchy is destroyed, but the fragment instance remains. Always nullify view references here.
3. Services
🎵 Foreground Service Pitfalls
class MusicService : Service() {
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
val notification = buildNotification() // Required for Android 8+
startForeground(NOTIFICATION_ID, notification)
return START_NOT_STICKY
}
// Binder for activity binding
inner class LocalBinder : Binder() { fun getService(): MusicService = this@MusicService }
}
Flowchart:
[startService()] → onStartCommand()
[bindService()] → onBind() → IBinder
[stopSelf()/stopService()] → onDestroy()
Interview Q:
Q: How to handle ANR in a started service?
A: Offload work to a background thread. Avoid blocking onStartCommand()
.
4. WorkManager
⏰ Chained Periodic Work
val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.setRequiresBatteryNotLow(true)
.build()
val request = PeriodicWorkRequestBuilder<SyncWorker>(1, TimeUnit.HOURS)
.setConstraints(constraints)
.build()
WorkManager.getInstance(context).enqueueUniquePeriodicWork(
"sync",
ExistingPeriodicWorkPolicy.KEEP, // Replace vs. keep existing
request
)
Execution Flow:
Worker.doWork() → [Background Thread]
│
├── Success → Result.success()
└── Failure → Result.retry()
Interview Q:
Q: When would WorkManager
NOT execute a worker?
A: If constraints aren’t met (e.g., no network) or OS battery optimizations (Doze mode) block execution.
5. Room Database
🚀 Migration Strategies
Schema Migration:
Room.databaseBuilder(appContext, AppDatabase::class.java, "mydb")
.addMigrations(object : Migration(1, 2) {
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("ALTER TABLE User ADD COLUMN age INTEGER")
}
})
.build()
DAO Optimization:
@Dao
interface UserDao {
@Transaction
@Query("SELECT * FROM User")
fun getUsersWithPosts(): Flow<List<UserWithPosts>> // Uses @Relation
@Query("SELECT * FROM User WHERE name LIKE :query")
fun searchUsers(query: String): Flow<List<User>>
}
Interview Q:
Q: How to handle Room CURSOR_WINDOW
exceptions?
A: Paginate large queries with LIMIT
/OFFSET
or use PagingSource
.
6. Coroutines & Flow
🌀 Structured Concurrency
viewModelScope.launch(Dispatchers.IO) {
val user = async { userRepo.getUser() }
val posts = async { postRepo.getPosts() }
val result = user.await() to posts.await()
withContext(Dispatchers.Main) { updateUI(result) }
}
Cancellation Rules:
- Cooperative Cancellation: Check
isActive
in loops. - Non-cancellable Blocks:
withContext(NonCancellable) { /* Critical cleanup */ }
Flow Operators:
userFlow
.filter { it.isActive }
.map { it.name }
.catch { e -> emit("Error") }
.collect { names -> println(names) }
Interview Q:
Q: Why does Flow.collect()
suspend?
A: To backpressure streams - collector controls emission rate.
7. Security
🔒 Encrypted SharedPreferences
val masterKey = MasterKey.Builder(context)
.setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
.build()
val sharedPreferences = EncryptedSharedPreferences.create(
context,
"secret_prefs",
masterKey,
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
)
sharedPreferences.edit().putString("API_KEY", "12345").apply()
Key Attestation:
- Use
KeyGenParameterSpec.Builder.setAttestationChallenge()
for hardware-backed keys.
Interview Q:
Q: How to prevent certificate pinning bypass in rooted devices?
A: Use obfuscation or runtime integrity checks (e.g., SafetyNet Attestation).
8. Performance Optimization
🛠️ Memory Leak Patterns
Leak 1: Static reference to Activity:
companion object {
var leakedActivity: Activity? = null // BAD!
}
Leak 2: Non-cancelled coroutines:
fun fetchData() {
GlobalScope.launch { /* Leak if Activity dies before completion */ }
}
Fix: Use viewModelScope
or lifecycleScope
.
Profiling Tools:
- Memory Profiler: Track heap allocations.
- Systrace: Identify UI jank.
Interview Q:
Q: How to debug a 120Hz UI freeze?
A: Check Choreographer
logs for skipped frames. Optimize onDraw()
/measure passes.
9. Dagger-Hilt
🔄 Component Hierarchies
@Module
@InstallIn(ViewModelComponent::class)
object ViewModelModule {
@Provides
fun provideDependency() = MyDependency()
}
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
@Inject lateinit var viewModelFactory: MyViewModelFactory
}
Scoping:
@Singleton
: App-level scope.@ViewModelScoped
: Lives as long as the ViewModel.
Interview Q:
Q: Why use @AssistedInject
with ViewModels?
A: To inject dependencies while allowing constructor params from the ViewModelProvider.Factory.
10. Espresso Testing
🧪 Idling Resources
class MyIdlingResource : IdlingResource {
override fun isIdleNow(): Boolean = /* Check if background work is done */
}
@Before
fun registerIdlingResource() {
IdlingRegistry.getInstance().register(idlingResource)
}
Synchronization:
- Espresso automatically waits for UI events and AsyncTasks.
- Custom Waits:
onView(withId(R.id.progress)).check(matches(not(isDisplayed())))
Interview Q:
Q: How to test RecyclerView item clicks?
A:
onView(withId(R.id.recycler))
.perform(actionOnItem<ViewHolder>(hasDescendant(withText("Item")), click()))
Appendix: Flowchart Legend
- Lifecycles: Use state transition diagrams (e.g.,
CREATED → STARTED → RESUMED
). - Data Flow:
UI → ViewModel → Repository → API/Database ↑ ↓ LiveData Coroutine
- Dependency Graph:
AppComponent → Subcomponents (Activity, Fragment) | ˪─ Provides Singletons
```
Final Notes
- Key Focus Areas:
- Lifecycle Awareness: Avoid leaks with
LifecycleObserver
. - Threading: Coroutine dispatchers,
withContext
best practices. - Performance:
SparseArray
overHashMap
,RecyclerView
view pooling.
- Lifecycle Awareness: Avoid leaks with
- Anti-Patterns:
- Using
runBlocking
in production. - Ignoring
StrictMode
warnings.
- Using
Let me know if you need further expansion on any topic! 🔥