Skip to content

PUBLIC QUESTION PREVIEW

Kotlin & Android interview questions

Kotlin language features, Android architecture (MVVM), Jetpack Compose, coroutines, Room, Retrofit, and testing.

Showing 12 of 40 source questions. Sample answers are study material, not employer-specific hiring guidance.

How to work through this preview

Attempt each question before reading its answer. For a concept, give a definition and a concrete example. For code, state constraints, walk through a small input, and check complexity. For design, separate requirements from assumptions and explain failure handling. Use real situations for behavioral answers.

QUESTION 1 / easy / conceptual

What is Kotlin? What advantages does it have over Java for Android development?

Sample answer

Kotlin: a modern, statically typed programming language developed by JetBrains, now Google's preferred language for Android development (since 2019). Key advantages over Java: 1. Null safety: - Types are non-nullable by default; nullable requires explicit ? annotation - Eliminates NullPointerException — the "billion-dollar mistake" var name: String = null // COMPILE ERROR var name: String? = null // OK — explicitly nullable 2. Concise syntax: // Java: List<User> adults = new ArrayList<>(); for (User u : users) { if (u.age >= 18) adults.add(u); } // Kotlin: val adults = users.filter { it.age >= 18 } 3. Coroutines (built-in concurrency): - Lightweight concurrency model without callback hell - Write async code that looks synchronous (launch, async, await) 4. Extension functions: - Add methods to existing classes without subclassing fun String.isValidEmail() = contains('@') && contains('.') 5. Data classes: - One line replaces 50+ lines of Java boilerplate (equals, hashCode, toString, copy) data class User(val id: Int, val name: String, val email: String) 6. Smart casts: if (obj is String) { println(obj.length) } // automatic cast inside the if block 7. Sealed classes, when expressions: - More powerful switch statements with exhaustive checking 8. 100% Java interoperability: - Use all existing Java libraries; Kotlin and Java can coexist in the same project Result: Android Studio survey shows teams report 20-40% fewer lines of code vs Java for equivalent features.

Hints to guide your next attempt

  • Null safety, concise syntax, coroutines, interoperable with Java

Source tags: kotlin / android / java / advantages / null-safety

QUESTION 2 / easy / conceptual

What are Kotlin data classes? What is generated automatically?

Sample answer

Data class: a class designed to hold data. The compiler automatically generates common utility functions based on the primary constructor's properties. Declaring: data class User(val id: Int, val name: String, val email: String, val age: Int = 0) Auto-generated: 1. equals(): structural equality based on all primary constructor properties val u1 = User(1, "Rahul", "r@test.com") val u2 = User(1, "Rahul", "r@test.com") println(u1 == u2) // true (structural equality, not reference equality) 2. hashCode(): consistent with equals; safe to use in HashMaps val map = mapOf(u1 to "active") map[u2] // works because hashCode is equal 3. toString(): readable representation println(u1) // User(id=1, name=Rahul, email=r@test.com, age=0) 4. copy(): create a modified copy without changing the original val updatedUser = u1.copy(email = "new@test.com") // u1 is unchanged; updatedUser has the new email 5. componentN() functions: for destructuring val (id, name, email) = u1 println(id) // 1 println(name) // Rahul Requirements and rules: - Primary constructor must have at least one parameter - All primary constructor parameters must be val or var - Cannot be abstract, open, sealed, or inner When to use vs regular class: - Use data class: for DTOs, API response models, Room entities, state objects in ViewModels - Use regular class: for classes with complex behaviour, mutable state patterns, services Kotlin data class vs Java record (Java 16+): - Similar concept; Kotlin data class has copy() and componentN which Java records lack - Kotlin data class predates Java records by many years

Hints to guide your next attempt

  • equals, hashCode, toString, copy, componentN functions generated automatically

Source tags: data-class / kotlin / equals / hashcode / copy / destructuring

QUESTION 3 / medium / conceptual

What are Kotlin sealed classes? When do you use them?

Sample answer

Sealed class: a class hierarchy where all direct subclasses are defined in the same package/file. The compiler knows all possible subclasses at compile time. sealed class UiState { object Loading : UiState() data class Success(val data: List<User>) : UiState() data class Error(val message: String) : UiState() } Exhaustive when expression — compiler enforces handling all cases: when (state) { is UiState.Loading -> showProgressBar() is UiState.Success -> showUsers(state.data) is UiState.Error -> showError(state.message) // No else needed — compiler knows these are all cases // Add a new subclass → compiler error until you handle it } vs enum: - enum: each value is an instance of the same class; can only have one set of properties - sealed class: each subclass can have different properties and its own data // enum: can't carry different data per state enum class Status { LOADING, SUCCESS, ERROR } // can't store the error message or user list Sealed interface (Kotlin 1.5+): sealed interface Result<out T> { data class Success<T>(val data: T) : Result<T> data class Error(val exception: Throwable) : Result<Nothing> object Loading : Result<Nothing> } // More flexible than sealed class (can implement multiple interfaces) Common use cases in Android: 1. ViewModel UI states: sealed class LoginState { object Idle : LoginState() object Loading : LoginState() data class Success(val token: String) : LoginState() data class Failure(val error: String) : LoginState() } 2. Navigation events: sealed class NavEvent { object NavigateToHome : NavEvent() data class NavigateToProfile(val userId: Int) : NavEvent() } 3. Network result wrapper: sealed class ApiResult<T> { data class Success<T>(val data: T) : ApiResult<T>() data class Error<T>(val code: Int, val message: String) : ApiResult<T>() class Loading<T> : ApiResult<T>() }

Hints to guide your next attempt

  • Closed class hierarchy, exhaustive when expressions
  • UI state, result types

Source tags: sealed-class / kotlin / when / ui-state / android

QUESTION 4 / medium / conceptual

What are Kotlin coroutines? How do they differ from threads?

Sample answer

Coroutines: Kotlin's way to write asynchronous, non-blocking code that looks sequential. Much lighter than OS threads. Coroutines vs Threads: - Thread: OS-managed, ~1-8MB stack, expensive to create/switch - Coroutine: managed by Kotlin runtime, ~few KB, can create millions, suspends (not blocks) the thread Key concepts: CoroutineScope: defines the lifecycle boundary for coroutines viewModelScope // auto-cancelled when ViewModel is cleared lifecycleScope // auto-cancelled when Activity/Fragment is destroyed GlobalScope // lives as long as app (usually avoid) Dispatchers: control which thread the coroutine runs on Dispatchers.Main // main thread (UI updates) Dispatchers.IO // thread pool for I/O (network, disk) Dispatchers.Default // thread pool for CPU-intensive work launch vs async: // launch: fire-and-forget (doesn't return a value) viewModelScope.launch { val users = repository.getUsers() // suspends here (non-blocking!) _uiState.value = UiState.Success(users) } // async: returns a Deferred<T> value; use await() to get result val userDeferred = viewModelScope.async { repository.getUser(1) } val user = userDeferred.await() // Parallel execution: val user = async(Dispatchers.IO) { repository.getUser(id) } val orders = async(Dispatchers.IO) { repository.getOrders(id) } // Both run in parallel: val (u, o) = Pair(user.await(), orders.await()) suspend functions: functions that can be paused and resumed without blocking a thread suspend fun getUser(id: Int): User = withContext(Dispatchers.IO) { api.fetchUser(id) // suspends while waiting for network } withContext: switch dispatcher within a coroutine fun loadUser() = viewModelScope.launch { // on Main thread initially val user = withContext(Dispatchers.IO) { api.getUser(1) } // back on Main thread _user.value = user }

Hints to guide your next attempt

  • Lightweight, suspendable, no thread blocking
  • launch vs async, Dispatchers

Source tags: coroutines / kotlin / async / suspend / dispatchers / android

QUESTION 5 / easy / conceptual

What is the Android Activity lifecycle? Name all callbacks.

Sample answer

Activity lifecycle: a set of callbacks that Android calls as the Activity transitions between visible/invisible and active/inactive states. Lifecycle callbacks in order: onCreate(): - First call; Activity is being created - Set up UI: setContentView(), ViewBinding, ViewModel - Called once unless Activity is destroyed and recreated (rotation) onStart(): - Activity becomes visible to the user but not yet interactive onResume(): - Activity is in the foreground and interactive - User can tap, type, interact - Start: camera, sensors, audio, animations onPause(): - Activity partially obscured (dialog opened, multi-window, another activity on top) - Stop: expensive operations (CPU-intensive animations, GPS continuous updates) - Must be fast — next Activity can't start until this completes onStop(): - Activity completely hidden from user (another app in foreground, home pressed) - Stop: heavy resources, save app state - Activity instance may be kept in memory onRestart(): - Called when Activity returns to the foreground from stopped state (not destroyed) - Follows: onStart() onDestroy(): - Activity is finishing (user pressed back, finish() called) OR system destroying to reclaim memory - Release all resources: close DB connections, cancel coroutines, unregister receivers Typical state flows: - App opens: onCreate → onStart → onResume - Home button: onPause → onStop - Return to app: onRestart → onStart → onResume - Back button: onPause → onStop → onDestroy - Screen rotation: onPause → onStop → onDestroy → onCreate → onStart → onResume onSaveInstanceState(bundle): - Called before Activity may be destroyed (rotation, system kill) - Save: UI state that should survive recreation - Restored in: onCreate(savedInstanceState) or onRestoreInstanceState() Best practice: use ViewModel for data that survives configuration changes; onSaveInstanceState for small UI state (scroll position, user input).

Hints to guide your next attempt

  • onCreate → onStart → onResume → onPause → onStop → onDestroy
  • When does each run?

Source tags: activity-lifecycle / android / oncreate / onresume / ondestroy

QUESTION 6 / medium / conceptual

What is the Fragment lifecycle? How does it relate to Activity lifecycle?

Sample answer

Fragment: a reusable UI component that is attached to an Activity. It has its own lifecycle that is tied to its host Activity. Fragment lifecycle callbacks: onAttach(context): Fragment is attached to Activity; access Activity context onCreate(): Fragment created; initialize non-UI components (ViewModels, data) onCreateView(): Inflate the Fragment's layout; return the root View onViewCreated(view, savedInstanceState): View is created; set up UI (RecyclerView adapters, click listeners, observers) onStart(): Fragment visible onResume(): Fragment interactive onPause(): Fragment partially obscured onStop(): Fragment hidden onDestroyView(): Fragment's view is being destroyed (Fragment instance may survive) onDestroy(): Fragment instance destroyed onDetach(): Fragment detached from Activity Key: onCreateView vs onViewCreated - onCreateView: inflate layout, return view — don't set up UI here - onViewCreated: safe to access views — set up RecyclerView, click listeners, observe LiveData/StateFlow here Fragment's view lifecycle (separate from Fragment lifecycle): viewLifecycleOwner // lifecycle of the current view (not the Fragment instance) // Always use viewLifecycleOwner for observing LiveData in a Fragment: viewModel.users.observe(viewLifecycleOwner) { users -> adapter.submitList(users) } // NOT: observe(this) — this causes memory leaks when view is destroyed but Fragment survives Relationship to Activity: - Activity starts → Fragment lifecycle starts (after Activity's onStart/onCreate) - Activity goes to background → Fragment pauses/stops - Activity rotates → Fragment view is destroyed and recreated; Fragment instance may survive (if added to back stack) When Fragment view survives but Fragment doesn't: - Fragment on back stack: view destroyed, instance kept - Always release binding in onDestroyView to avoid memory leaks Fragment back stack: // Add Fragment to back stack (pressing Back restores previous Fragment): fragmentManager.commit { replace(R.id.container, DetailFragment()) addToBackStack(null) }

Hints to guide your next attempt

  • Fragment has its own lifecycle nested inside Activity lifecycle
  • onAttach, onCreateView, onViewCreated

Source tags: fragment / lifecycle / android / onviewcreated / viewlifecycleowner

QUESTION 7 / medium / conceptual

What is MVVM architecture in Android? Explain the role of ViewModel, LiveData, and Repository.

Sample answer

MVVM (Model-View-ViewModel): Android's recommended architecture pattern separating UI, business logic, and data. Layers: View (Activity/Fragment): - Displays data; forwards user actions to ViewModel - Observes ViewModel state; never holds business logic - Thin: only UI-related code ViewModel: - Holds and manages UI state; survives configuration changes (rotation) - Contains business logic; coordinates between View and Repository - Exposes data via LiveData/StateFlow - Has no reference to Activity/Fragment/Context (prevents memory leaks) class UserViewModel(private val repository: UserRepository) : ViewModel() { private val _users = MutableLiveData<List<User>>() val users: LiveData<List<User>> = _users fun loadUsers() { viewModelScope.launch { val data = repository.getUsers() _users.value = data } } } Repository: - Abstracts data sources (network API, Room DB, cache) - ViewModel doesn't know whether data comes from network or cache - Single source of truth pattern class UserRepository(private val api: ApiService, private val dao: UserDao) { suspend fun getUsers(): List<User> { return try { val users = api.fetchUsers() dao.insertAll(users) // cache in Room users } catch (e: Exception) { dao.getAllUsers() // serve from cache on failure } } } LiveData: - Lifecycle-aware observable data holder - Observers (Activity/Fragment) automatically removed when lifecycle stops → no memory leaks - Only updates UI when lifecycle is active (STARTED or RESUMED) Full data flow: User action → View → ViewModel → Repository → API/DB Data → Repository → ViewModel (updates LiveData) → View observes → UI updated Benefits of MVVM: - Testability: test ViewModel with mock repository; no Android framework in unit tests - Separation of concerns: each layer has one responsibility - Rotation survival: ViewModel keeps data alive through configuration changes

Hints to guide your next attempt

  • Separation of concerns
  • ViewModel survives rotation, Repository abstracts data sources

Source tags: mvvm / viewmodel / livedata / repository / android / architecture

QUESTION 8 / medium / conceptual

What is the difference between LiveData and StateFlow/SharedFlow?

Sample answer

Both are observable data holders, but they differ in lifecycle awareness and API. LiveData: - Part of Android Architecture Components (not Kotlin-specific) - Lifecycle-aware: only notifies observers when they are in STARTED or RESUMED state - Does NOT require coroutines; callbacks-based internally - Always has a "current value" (default null) class ViewModel : ViewModel() { private val _name = MutableLiveData<String>() val name: LiveData<String> = _name fun update(n: String) { _name.value = n } // main thread fun updateAsync(n: String) { _name.postValue(n) } // background thread } // Observe in Fragment: viewModel.name.observe(viewLifecycleOwner) { name -> textView.text = name } StateFlow (Kotlin coroutines): - Part of Kotlin Flow (not Android-specific) - Always has a value (requires initial value) - Hot flow: emits to collectors regardless of lifecycle - Requires manual lifecycle collection in the View class ViewModel : ViewModel() { private val _name = MutableStateFlow("") val name: StateFlow<String> = _name.asStateFlow() fun update(n: String) { _name.value = n } } // Collect in Fragment (lifecycle-safe): viewLifecycleOwner.lifecycleScope.launch { viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) { viewModel.name.collect { name -> textView.text = name } } } SharedFlow: - Like StateFlow but no initial value requirement; can emit events (one-time side effects) - configurable replay (replay = 0 for events that shouldn't be replayed on collection) - Use for: navigation events, snackbar messages (emit once, not replay) private val _navEvent = MutableSharedFlow<NavEvent>() val navEvent = _navEvent.asSharedFlow() When to use: - StateFlow: UI state (current screen state, user data) - SharedFlow(replay=0): one-time events (navigation, toast, error dialog) - LiveData: legacy code, or when you prefer no-coroutine setup in View Modern recommendation: StateFlow + SharedFlow for new code. LiveData is still supported but less idiomatic with coroutines.

Hints to guide your next attempt

  • LiveData is lifecycle-aware, StateFlow is coroutine-based
  • StateFlow is preferred for new code

Source tags: livedata / stateflow / sharedflow / kotlin / android / flow

QUESTION 9 / medium / conceptual

What is Room? How do you define a database, DAO, and Entity?

Sample answer

Room: Android's official ORM (Object-Relational Mapper) for SQLite. Provides compile-time query verification and coroutine/Flow support. Three components: 1. Entity — maps to a database table: @Entity(tableName = "users") data class UserEntity( @PrimaryKey val id: Int, @ColumnInfo(name = "user_name") val name: String, val email: String, val createdAt: Long = System.currentTimeMillis() ) 2. DAO (Data Access Object) — SQL operations: @Dao interface UserDao { @Query("SELECT * FROM users ORDER BY user_name ASC") fun getAllUsers(): Flow<List<UserEntity>> // returns Flow for reactive updates @Query("SELECT * FROM users WHERE id = :userId") suspend fun getUserById(userId: Int): UserEntity? @Insert(onConflict = OnConflictStrategy.REPLACE) suspend fun insertUser(user: UserEntity) @Insert suspend fun insertAll(users: List<UserEntity>) @Update suspend fun updateUser(user: UserEntity) @Delete suspend fun deleteUser(user: UserEntity) @Query("DELETE FROM users WHERE id = :userId") suspend fun deleteById(userId: Int) } 3. Database — ties it together: @Database(entities = [UserEntity::class], version = 1, exportSchema = false) abstract class AppDatabase : RoomDatabase() { abstract fun userDao(): UserDao companion object { @Volatile private var INSTANCE: AppDatabase? = null fun getInstance(context: Context): AppDatabase = INSTANCE ?: synchronized(this) { Room.databaseBuilder(context.applicationContext, AppDatabase::class.java, "app_database") .build().also { INSTANCE = it } } } } Usage in Repository: class UserRepository(private val userDao: UserDao) { val allUsers: Flow<List<UserEntity>> = userDao.getAllUsers() // observe DB changes suspend fun insert(user: UserEntity) = userDao.insertUser(user) } Migrations (schema changes): val MIGRATION_1_2 = object : Migration(1, 2) { override fun migrate(database: SupportSQLiteDatabase) { database.execSQL("ALTER TABLE users ADD COLUMN age INTEGER NOT NULL DEFAULT 0") } } // Add to databaseBuilder: .addMigrations(MIGRATION_1_2)

Hints to guide your next attempt

  • ORM on top of SQLite
  • @Entity, @Dao, @Database, @Query annotations

Source tags: room / sqlite / dao / entity / android / database

QUESTION 10 / medium / conceptual

What is Retrofit? How do you make network calls in Android?

Sample answer

Retrofit: a type-safe HTTP client for Android and Java. Turns REST API descriptions into usable Kotlin interfaces. Setup (Gradle): implementation("com.squareup.retrofit2:retrofit:2.9.0") implementation("com.squareup.retrofit2:converter-gson:2.9.0") implementation("com.squareup.okhttp3:logging-interceptor:4.12.0") Define API interface: interface ApiService { @GET("users") suspend fun getUsers(): List<UserDto> @GET("users/{id}") suspend fun getUserById(@Path("id") id: Int): UserDto @POST("users") suspend fun createUser(@Body request: CreateUserRequest): UserDto @PUT("users/{id}") suspend fun updateUser(@Path("id") id: Int, @Body request: UpdateUserRequest): UserDto @DELETE("users/{id}") suspend fun deleteUser(@Path("id") id: Int): Response<Unit> @GET("search") suspend fun searchUsers(@Query("q") query: String, @Query("page") page: Int): PagedResult<UserDto> @GET("users") suspend fun getUsersWithHeader(@Header("Authorization") token: String): List<UserDto> } Create Retrofit instance (singleton): val retrofit = Retrofit.Builder() .baseUrl("https://api.example.com/") .addConverterFactory(GsonConverterFactory.create()) .client(OkHttpClient.Builder() .addInterceptor(HttpLoggingInterceptor().apply { level = HttpLoggingInterceptor.Level.BODY }) .addInterceptor { chain -> val request = chain.request().newBuilder() .addHeader("Authorization", "Bearer ${getToken()}") .build() chain.proceed(request) } .connectTimeout(30, TimeUnit.SECONDS) .readTimeout(30, TimeUnit.SECONDS) .build()) .build() val apiService: ApiService = retrofit.create(ApiService::class.java) Use in Repository with error handling: suspend fun getUsers(): Result<List<User>> = try { val response = apiService.getUsers() Result.success(response.map { it.toDomain() }) } catch (e: HttpException) { Result.failure(Exception("HTTP ${e.code()}: ${e.message()}")) } catch (e: IOException) { Result.failure(Exception("Network error: ${e.message}")) } Use in ViewModel: viewModelScope.launch { val result = repository.getUsers() result.onSuccess { _users.value = it } result.onFailure { _error.value = it.message } }

Hints to guide your next attempt

  • Type-safe HTTP client, suspend functions, Gson/Moshi converters

Source tags: retrofit / networking / kotlin / android / api / okhttp

QUESTION 11 / medium / conceptual

What is Hilt? How does dependency injection work in Android?

Sample answer

Hilt: Android's recommended DI (Dependency Injection) library, built on top of Dagger 2 but with significantly less boilerplate. Why DI: - Manually constructing dependencies (val repo = UserRepository(ApiService(), UserDao())) throughout code creates tight coupling and makes testing hard - DI: declare what you need; the framework provides it (inversion of control) Setup: @HiltAndroidApp — annotate Application class (required): @HiltAndroidApp class MyApp : Application() @AndroidEntryPoint — annotate Activity/Fragment to enable injection: @AndroidEntryPoint class MainActivity : AppCompatActivity() { @Inject lateinit var analyticsService: AnalyticsService } @HiltViewModel — ViewModel injection: @HiltViewModel class UserViewModel @Inject constructor( private val repository: UserRepository ) : ViewModel() // Fragment/Activity: automatically provided by Hilt val viewModel: UserViewModel by viewModels() Providing dependencies (Module): @Module @InstallIn(SingletonComponent::class) object NetworkModule { @Provides @Singleton fun provideOkHttpClient(): OkHttpClient = OkHttpClient.Builder().build() @Provides @Singleton fun provideRetrofit(client: OkHttpClient): Retrofit = Retrofit.Builder().baseUrl(BASE_URL).client(client) .addConverterFactory(GsonConverterFactory.create()).build() @Provides @Singleton fun provideApiService(retrofit: Retrofit): ApiService = retrofit.create(ApiService::class.java) } Scopes: - @Singleton: one instance per app lifetime - @ActivityRetainedScoped: survives rotation, same as ViewModel scope - @ActivityScoped: one per Activity - @ViewModelScoped: one per ViewModel Interface binding: @Module @InstallIn(SingletonComponent::class) abstract class RepositoryModule { @Binds @Singleton abstract fun bindUserRepository(impl: UserRepositoryImpl): UserRepository } Benefits: - Remove manual DI plumbing code - Easy to swap implementations for testing (provide a FakeRepository in tests) - Compile-time validation (DI wiring errors caught at build time)

Hints to guide your next attempt

  • Built on Dagger, scoped components
  • @HiltAndroidApp, @Inject, @Module, @Provides

Source tags: hilt / dependency-injection / dagger / android / kotlin

QUESTION 12 / medium / conceptual

What is Jetpack Compose? How does it compare to XML-based Views?

Sample answer

Jetpack Compose: Android's modern, declarative UI toolkit using Kotlin. Instead of XML layouts + ViewBinding, UI is defined as Kotlin functions. Core concept: UI = f(state). When state changes, the UI automatically recomposes (re-renders the affected parts). Composable function: @Composable fun UserCard(user: User, onFavorite: (User) -> Unit) { Card( modifier = Modifier.fillMaxWidth().padding(8.dp), elevation = CardDefaults.cardElevation(4.dp) ) { Row(verticalAlignment = Alignment.CenterVertically) { AsyncImage(model = user.avatarUrl, contentDescription = null, modifier = Modifier.size(48.dp).clip(CircleShape)) Column(modifier = Modifier.weight(1f).padding(start = 12.dp)) { Text(text = user.name, style = MaterialTheme.typography.titleMedium) Text(text = user.email, style = MaterialTheme.typography.bodySmall) } IconButton(onClick = { onFavorite(user) }) { Icon(Icons.Filled.Favorite, contentDescription = "Favourite") } } } } State in Compose: @Composable fun Counter() { var count by remember { mutableStateOf(0) } // state survives recomposition Button(onClick = { count++ }) { Text("Count: $count") } } // ViewModel state: val uiState by viewModel.uiState.collectAsStateWithLifecycle() Compose vs XML Views: | Aspect | XML Views | Jetpack Compose | | Language | XML + Kotlin | Kotlin only | | UI definition | Declarative XML + imperative code | Fully declarative Kotlin | | State handling | Manual (setText, etc.) | Automatic recomposition | | Boilerplate | ViewBinding/Inflation | Minimal | | Interoperability | N/A | Can embed Views in Compose + Compose in Views | | Performance | Mature | Improving rapidly | When to use Compose: - New projects: use Compose from day one - Existing projects: migrate screen by screen using ComposeView in XML layouts - Google recommends Compose for all new development (2024+)

Hints to guide your next attempt

  • Declarative UI, recomposition, Composable functions
  • No XML, no ViewBinding

Source tags: jetpack-compose / declarative-ui / android / kotlin / recomposition

Check understanding, not recognition

  • Can you explain the answer without reading it?
  • Can you show when the approach fails or needs a different assumption?
  • Can you connect the concept to a real project, task, or decision you have made?
  • Can you distinguish a simplified interview example from a production requirement?

A LITTLE MORE CLARITY

Frequently asked questions

How many Kotlin & Android questions are shown here?

This public preview shows 12 questions with the supplied answers from the app's 40-question Kotlin & Android bank. Full interactive practice requires signing in.

Should I memorize the sample answers?

Use them as reference explanations, not a script or a guarantee of technical correctness for every environment. Explain your assumptions, validate code against your language and version, and discuss trade-offs. Behavioral answers should be built from your own experience.

What do hints and solution steps mean?

Hints identify ideas to consider before reading the answer. When the source question includes steps, they are shown as a separate walkthrough. Example capacities and design targets in a solution are assumptions for that exercise, not real system statistics.

BUILD YOUR NEXT OPPORTUNITY

Practice Kotlin & Android actively.

Sign in to use the full topic bank and interactive practice workspace.

Open Topic Practice