Skip to content

Easy Android App Development Interview Questions

60 easy questions with answers. Definitions and fundamentals every candidate must answer quickly and correctly.

Topics in the easy set

Kotlin Fundamentals: 12 Jetpack Compose: 10 Android Components and Lifecycle: 8 Room, DataStore and WorkManager: 7 Testing, Performance and Play Store: 7 Coroutines and Flow: 6 App Architecture, MVVM and Hilt: 6 Networking and APIs: 4
Solved — easyStart practicing
3 QUESTIONS FREESign up to unlock the full question bank and track your progress.Unlock every question and answer, then continue practising company-wise and package-wise.
3 questions free Unlock the rest in seconds
01

What is the difference between val and var in Kotlin?

Save to ▾
Show answer
val declares a read-only reference that cannot be reassigned after initialisation, while var declares a mutable reference. Note that val does not make the object immutable: a val pointing to a MutableList can still have items added. Prefer val by default because it makes code easier to reason about and safer in concurrent code, and switch to var only when reassignment is genuinely needed.
02

How does Kotlin handle null safety?

Save to ▾
Show answer
Kotlin's type system separates nullable types (String?) from non-nullable types (String). The compiler stops you calling methods on a nullable value without a check. You use the safe call operator ?., the Elvis operator ?: for defaults, smart casts after null checks, or !! to force a value and risk a NullPointerException. This moves most null crashes from runtime to compile time, which is a major reason Android adopted Kotlin.
03

What is a data class and what does the compiler generate for it?

Save to ▾
Show answer
A data class is a class meant to hold data, declared with the data keyword and at least one property in the primary constructor. The compiler generates equals(), hashCode(), toString(), copy() and componentN() functions for destructuring, all based on primary constructor properties. They are ideal for UI state, API models and Room entities. Properties declared in the class body are not included in the generated equals or toString.
04

Write a sealed interface for a screen state and handle it with when.

Save to ▾
Show answer
sealed interface UiState { data object Loading : UiState data class Success(val items: List<String>) : UiState data class Error(val message: String) : UiState } fun render(state: UiState) = when (state) { UiState.Loading -> showProgress() is UiState.Success -> showList(state.items) is UiState.Error -> showError(state.message) }
05

What is the difference between == and === in Kotlin?

Save to ▾
Show answer
== checks structural equality and calls equals() under the hood, handling nulls safely. === checks referential equality, meaning both references point to the same object in memory. For two data class instances with the same values, == returns true but === returns false unless they are the same instance. For primitive-like types such as Int, === may behave unexpectedly due to boxing, so == is the normal choice.
06

What are higher-order functions and lambdas in Kotlin?

Save to ▾
Show answer
A higher-order function takes a function as a parameter or returns one. A lambda is an anonymous function literal like { x: Int -> x * 2 }. Collection operations such as map, filter and forEach are higher-order functions. In Android you see them in click listeners, Compose callbacks like onClick = { } and coroutine builders. If the last parameter is a function, the lambda can be written outside the parentheses, known as trailing lambda syntax.
07

Write a Kotlin function that groups a list of orders by city and returns total amount per city.

Save to ▾
Show answer
data class Order(val city: String, val amount: Double) fun totalsByCity(orders: List<Order>): Map<String, Double> = orders.groupBy { it.city } .mapValues { (_, list) -> list.sumOf { it.amount } } // Alternative with one pass: // orders.groupingBy { it.city }.fold(0.0) { acc, o -> acc + o.amount }
08

How do default and named arguments reduce the need for overloads?

Save to ▾
Show answer
Kotlin functions can define default values, such as fun showToast(msg: String, long: Boolean = false), so callers skip arguments they do not need. Named arguments, like showToast(msg = "Saved", long = true), make calls readable and let you change argument order. Together they replace telescoping constructors and builder patterns in many cases. For Java callers, add @JvmOverloads so overloads are generated automatically.
09

A teammate uses !! everywhere to silence compiler errors. How do you handle this in code review?

Save to ▾
Show answer
Explain calmly that !! converts a compile-time check into a possible runtime crash. Suggest alternatives per case: safe calls with ?.let, Elvis with a default or early return, requireNotNull with a clear message, or fixing the type at the source so it is non-null. Add a detekt rule to flag !! in new code. Pair with them on one file so the change feels like help, not criticism.
10

Write a function that safely parses a string to an Int and returns a default on failure.

Save to ▾
Show answer
fun String?.toIntOrDefault(default: Int = 0): Int = this?.trim()?.toIntOrNull() ?: default // Usage val qty = input.text.toString().toIntOrDefault(1) val age = null.toIntOrDefault() // 0
11

Tell me about a time you learned a new language or framework quickly for a project.

Save to ▾
Show answer
Situation: my team switched a feature to Kotlin when I only knew Java. Task: deliver a profile screen in two weeks. Action: I spent the first evenings on the official Kotlin koans, converted small utility classes first, and asked a senior to review my early pull requests for idiomatic usage. Result: the screen shipped on time, and my later code needed far fewer review comments. I now learn by building something small immediately.
12

Why should we hire you as a fresher Android developer?

Save to ▾
Show answer
Give evidence, not adjectives. For example: I have built and published two apps using Kotlin and Jetpack Compose, one with Room and Retrofit and an MVVM structure, and both are on my GitHub with a README and tests. I debug by reading logs and stack traces before asking for help, and I am comfortable learning from code reviews. I can contribute to bug fixes and small features from the first month.
13

What is a coroutine and how is it different from a thread?

Save to ▾
Show answer
A coroutine is a suspendable computation that can pause at suspension points without blocking the thread it runs on. Thousands of coroutines can share a small thread pool because suspended coroutines do not hold a thread. Threads are managed by the OS, are heavier in memory and context switching. On Android, coroutines let you write asynchronous code like network calls in a sequential style, without callbacks, while keeping the main thread free.
14

What does the suspend keyword mean?

Save to ▾
Show answer
suspend marks a function that can pause and resume later without blocking the thread. It can only be called from another suspend function or a coroutine. The compiler transforms it using continuation-passing style into a state machine. suspend alone does not move work to a background thread; the function must use withContext(Dispatchers.IO) or a main-safe library like Retrofit or Room to avoid blocking the main thread.
15

Explain Dispatchers.Main, IO and Default.

Save to ▾
Show answer
Dispatchers.Main runs on the Android UI thread and is used for updating views or state. Dispatchers.IO uses a large shared pool, by default up to 64 threads, for blocking work like disk and network. Dispatchers.Default uses a pool sized to CPU cores for CPU-heavy work like sorting, parsing large JSON or image processing. Use withContext to switch, and keep suspend functions main-safe so callers do not need to know.
16

What is the difference between launch and async?

Save to ▾
Show answer
launch starts a coroutine for work that returns no result and gives back a Job you can cancel or join. async returns a Deferred<T>, and you call await() to get the result. Use async to run independent tasks in parallel, such as fetching profile and orders together, then awaiting both. Exceptions differ: launch propagates them to the parent immediately, while async holds them until await, though in structured concurrency the parent still gets cancelled.
17

What is Kotlin Flow and how is it different from a suspend function?

Save to ▾
Show answer
A suspend function returns a single value once. A Flow is a cold asynchronous stream that emits multiple values over time, like database updates, location changes or search results. Cold means the code inside flow { } runs only when collected, and runs again for each collector. Room, DataStore and many libraries expose Flow so the UI automatically updates when underlying data changes.
18

How do you keep up with changes in Kotlin and Android?

Save to ▾
Show answer
I follow the Android Developers blog and release notes for Jetpack libraries, read the Kotlin release notes for each version, and watch sessions from the main yearly Android conferences. I try new APIs in a small side project before proposing them at work, and I read pull requests from experienced colleagues. Once a month I review deprecation warnings in our project so upgrades stay small and planned.
19

What are the four main Android app components?

Save to ▾
Show answer
Activities provide a screen the user interacts with. Services run work without a UI, such as music playback. Broadcast receivers respond to system or app-wide events like boot completed or connectivity change. Content providers share structured data between apps, such as contacts. Each component is an entry point the system can start, and most must be declared in AndroidManifest.xml with appropriate intent filters and permissions.
20

Explain the Activity lifecycle.

Save to ▾
Show answer
onCreate runs once to set up the UI and state. onStart makes the activity visible, onResume makes it interactive in the foreground. onPause runs when it loses focus, onStop when it is no longer visible, and onDestroy before it is removed. Rotation by default destroys and recreates the activity. Release resources like camera in onPause or onStop, and save transient UI state with ViewModel and SavedStateHandle.
21

What happens on a configuration change such as screen rotation?

Save to ▾
Show answer
By default the system destroys and recreates the Activity so it can load resources for the new configuration, like landscape layouts or a new language. Fields in the Activity are lost, but a ViewModel survives because it is kept by the ViewModelStore. Views with IDs restore some state automatically, and rememberSaveable in Compose restores small state. Handling changes manually via configChanges is possible but should be a deliberate choice.
22

What is the difference between explicit and implicit intents?

Save to ▾
Show answer
An explicit intent names the exact component to start, like Intent(this, DetailActivity::class.java), and is used inside your own app. An implicit intent declares an action and data, such as ACTION_VIEW with a URL or ACTION_SEND with text, and the system finds apps that can handle it through intent filters. For implicit intents, handle the case where no app can respond, and since Android 11 declare package visibility queries when needed.
23

How do runtime permissions work in modern Android?

Save to ▾
Show answer
Dangerous permissions like camera, location and notifications (POST_NOTIFICATIONS since Android 13) must be declared in the manifest and requested at runtime. Use the Activity Result API with RequestPermission or RequestMultiplePermissions contracts. Show a rationale when shouldShowRequestPermissionRationale returns true, handle denial gracefully, and direct users to settings if they deny permanently. Request permissions in context, at the moment the feature needs them.
24

What is the role of AndroidManifest.xml?

Save to ▾
Show answer
The manifest declares the app's package identity, components (activities, services, receivers, providers), intent filters, permissions, hardware features, and app-level settings like theme, backup rules and exported flags. Since Android 12, components with intent filters must set android:exported explicitly. Gradle merges manifests from libraries into the final one, so check the merged manifest when unexpected permissions appear in your release build.
25

What is the difference between Parcelable and Serializable?

Save to ▾
Show answer
Serializable is a Java marker interface that uses reflection and creates many temporary objects, so it is slower. Parcelable is Android-specific and writes fields explicitly to a Parcel, which is much faster for IPC. Writing Parcelable by hand is verbose, but the kotlin-parcelize plugin with @Parcelize generates it. Use Parcelable for Bundles and intents, and never use either as a long-term storage format.
26

How do you explain a technical limitation to a non-technical product manager?

Save to ▾
Show answer
I focus on user impact and options rather than jargon. For example, when asked for background tracking every second, I explained that Android limits background work to save battery, so the app would need a visible notification and stricter Play review. I offered two options with trade-offs and a recommendation. Using a simple diagram helped, and the PM chose the option that met the business need with fewer risks.
27

What is Jetpack Compose and how is it different from XML views?

Save to ▾
Show answer
Jetpack Compose is Android's modern declarative UI toolkit. You describe the UI as Kotlin functions of state, and Compose redraws the parts that change when state changes. With XML views you inflate layouts and imperatively update views with findViewById or binding. Compose removes adapters and much boilerplate, makes theming and previews easier, and interoperates with views through ComposeView and AndroidView, allowing gradual migration.
28

What is recomposition?

Save to ▾
Show answer
Recomposition is Compose re-running composable functions whose inputs or read state changed, to update the UI. Compose tries to skip composables whose parameters are stable and unchanged. Composables can run often and in any order, so they must be side-effect free and fast; do not make network calls or write to variables inside them. Use Layout Inspector recomposition counts to find composables recomposing more than expected.
29

What is the difference between remember and rememberSaveable?

Save to ▾
Show answer
remember keeps a value across recompositions but loses it when the composable leaves composition, on configuration change or process death. rememberSaveable stores the value in the saved instance state Bundle, so it survives rotation and process death; it works with types that can go in a Bundle or with a custom Saver. Use rememberSaveable for things like text input or selected tab, and a ViewModel for screen-level data.
30

What is state hoisting in Compose?

Save to ▾
Show answer
State hoisting means moving state out of a composable to its caller, and passing the value plus event callbacks down, like value and onValueChange. The composable becomes stateless, reusable and easy to preview and test. State should be hoisted to the lowest common parent that needs to read or change it, and screen-level state usually lives in a ViewModel. This creates unidirectional data flow: state flows down, events flow up.
31

Write a stateless text field with a hoisted state and validation message.

Save to ▾
Show answer
@Composable fun EmailField( value: String, onValueChange: (String) -> Unit, error: String?, modifier: Modifier = Modifier ) { OutlinedTextField( value = value, onValueChange = onValueChange, label = { Text("Email") }, isError = error != null, supportingText = { error?.let { Text(it) } }, singleLine = true, modifier = modifier.fillMaxWidth() ) }
32

Write a LazyColumn that shows a list of products with keys and a click handler.

Save to ▾
Show answer
@Composable fun ProductList( products: List<Product>, onClick: (Product) -> Unit ) { LazyColumn( contentPadding = PaddingValues(16.dp), verticalArrangement = Arrangement.spacedBy(8.dp) ) { items(products, key = { it.id }) { product -> ListItem( headlineContent = { Text(product.name) }, supportingContent = { Text("Rs ${product.price}") }, modifier = Modifier.clickable { onClick(product) } ) } } }
33

Why does the order of modifiers matter?

Save to ▾
Show answer
Modifiers are applied in a chain from left to right, each wrapping the next. Modifier.padding(16.dp).background(Color.Red) adds padding outside the red area, while background first then padding colours the padding too. Similarly, clickable before padding makes the whole padded area clickable. Thinking of each modifier as wrapping the content after it helps predict layout, size and touch target behaviour.
34

How do you collect a ViewModel StateFlow in a composable?

Save to ▾
Show answer
Use val state by viewModel.uiState.collectAsStateWithLifecycle() from lifecycle-runtime-compose. It collects only while the lifecycle is at least STARTED, saving resources in the background, unlike collectAsState which keeps collecting. Pass the resulting state and callbacks to a stateless screen composable, which keeps the screen previewable and testable without a ViewModel. Obtain the ViewModel with hiltViewModel() or viewModel() at the route level.
35

A composable makes an API call every time the screen recomposes. What is wrong and how do you fix it?

Save to ▾
Show answer
The call is placed directly in the composable body, which runs on every recomposition. Composables must be side-effect free. Move loading to the ViewModel, triggered in init or by a user event, and expose the result as StateFlow. If something must start from composition, wrap it in LaunchedEffect with a stable key like the item ID, so it runs once per key rather than on every recomposition.
36

A text field loses its typed value after rotation. How do you fix it?

Save to ▾
Show answer
The value is probably held with remember, which is lost when the Activity is recreated. Either use rememberSaveable for local UI state, or keep the text in the ViewModel and pass it down with onValueChange. For data that must survive process death too, store it in SavedStateHandle in the ViewModel. Avoid storing text field state asynchronously, because delayed updates can cause cursor jumps.
37

What is MVVM and why is it recommended for Android?

Save to ▾
Show answer
MVVM splits an app into Model (data and business logic), View (Activity, Fragment or composable that renders state) and ViewModel (holds UI state and handles user events). The ViewModel survives configuration changes and has no reference to views, so it is easy to unit test. The View observes state from the ViewModel through StateFlow or LiveData. This separation reduces bugs from lifecycle issues and keeps UI code thin.
38

Why should a ViewModel never hold a reference to an Activity, Fragment or View?

Save to ▾
Show answer
A ViewModel outlives the Activity during configuration changes. If it holds the old Activity or a view, that Activity cannot be garbage collected after rotation, causing a memory leak and possibly crashes when updating a dead view. Expose state for the UI to observe instead. If you need a Context for resources, inject the Application context or better, move that work into a repository or use resource IDs in state.
39

What is unidirectional data flow?

Save to ▾
Show answer
In unidirectional data flow, state flows down from the ViewModel to the UI, and events flow up from the UI to the ViewModel. The UI never changes state directly; it calls functions like onAddToCart(id), the ViewModel updates an immutable state object, and the UI re-renders. This makes state changes predictable, traceable and testable, and it is the model that Jetpack Compose is built around.
40

What is dependency injection and why use Hilt?

Save to ▾
Show answer
Dependency injection means classes receive their dependencies from outside rather than creating them, making code testable and loosely coupled. Hilt, built on Dagger, is Jetpack's recommended DI library. It generates code at compile time, provides standard components tied to Android lifecycles (SingletonComponent, ActivityRetainedComponent, ViewModelComponent), and integrates with ViewModels via @HiltViewModel. Errors appear at compile time rather than runtime.
41

Unit tests for a ViewModel are hard to write because it creates the repository inside itself. What do you change?

Save to ▾
Show answer
Constructor-inject the repository as an interface, so tests can pass a fake implementation. With Hilt, add @Inject to the constructor and bind the real implementation in a module. Also inject dispatchers rather than using Dispatchers.IO directly. Then tests create ViewModel(FakeRepository()) and control results precisely. This change improves design too, because the ViewModel no longer knows how data is created.
42

A new developer asks why we need interfaces for every repository. How do you answer?

Save to ▾
Show answer
Interfaces let us swap implementations, mainly fakes in tests and alternate data sources, and they define clear contracts between modules so feature modules depend on abstractions instead of concrete network code. But the rule is not absolute: if a class has one implementation and is easy to test directly, an interface adds noise. I would explain the reason with an example test and our team convention.
43

What is Room and what are its main components?

Save to ▾
Show answer
Room is the Jetpack persistence library built on SQLite. Its main parts are @Entity classes that map to tables, @Dao interfaces with queries annotated by @Query, @Insert, @Update and @Delete, and an abstract @Database class that ties them together. Room verifies SQL at compile time, supports suspend functions and Flow return types, and handles migrations. It removes most SQLite boilerplate while keeping full SQL power.
44

Write a Room entity and DAO for notes with a Flow query.

Save to ▾
Show answer
@Entity(tableName = "notes") data class NoteEntity( @PrimaryKey(autoGenerate = true) val id: Long = 0, val title: String, val body: String, val updatedAt: Long ) @Dao interface NoteDao { @Query("SELECT * FROM notes ORDER BY updatedAt DESC") fun observeAll(): Flow<List<NoteEntity>> @Upsert suspend fun upsert(note: NoteEntity) @Query("DELETE FROM notes WHERE id = :id") suspend fun delete(id: Long) }
45

What is DataStore and why does it replace SharedPreferences?

Save to ▾
Show answer
Jetpack DataStore stores key-value pairs (Preferences DataStore) or typed objects (Proto DataStore) using coroutines and Flow. Unlike SharedPreferences, it is safe to call from the main thread because I/O is asynchronous, it reports errors through exceptions, and updates are transactional. SharedPreferences apply() can still block the main thread during lifecycle events and cause ANRs. Use one DataStore instance per file, ideally as a singleton.
46

Write code to save and read a dark mode preference with Preferences DataStore.

Save to ▾
Show answer
val Context.dataStore by preferencesDataStore(name = "settings") private val DARK_MODE = booleanPreferencesKey("dark_mode") class SettingsRepository(private val context: Context) { val darkMode: Flow<Boolean> = context.dataStore.data .catch { emit(emptyPreferences()) } .map { it[DARK_MODE] ?: false } suspend fun setDarkMode(enabled: Boolean) { context.dataStore.edit { it[DARK_MODE] = enabled } } }
47

What is WorkManager and when should you use it?

Save to ▾
Show answer
WorkManager schedules deferrable, guaranteed background work that must run even if the app exits or the device restarts, such as syncing data, uploading logs or backing up photos. It supports constraints like network or charging, retries with backoff, chaining and unique work. It is not for exact-time tasks or work that must finish immediately while the user waits; use coroutines for that and AlarmManager for exact alarms.
48

How do you prioritise when you have several bugs and a feature deadline in the same week?

Save to ▾
Show answer
I rank by user impact and risk: crashes and data loss first, then bugs affecting payments or login, then the feature, then minor UI issues. I share the plan with my lead and product manager so trade-offs are visible, and I ask for help or a scope cut early instead of quietly missing the deadline. Small, safe fixes I batch together to save release overhead.
49

A user complains the app uses too much storage. How do you find and reduce it?

Save to ▾
Show answer
Check Settings storage breakdown and inspect filesDir, cacheDir and databases with Device Explorer. Common culprits are unbounded image caches, old downloaded files, logs, and databases that never delete old rows. Set size limits on Coil and OkHttp caches, use cacheDir for temporary files so the system can clear them, delete old records with a periodic WorkManager job, and compress or downscale stored images.
50

What is Retrofit and how does it work with coroutines?

Save to ▾
Show answer
Retrofit is a type-safe HTTP client that turns an annotated Kotlin interface into API calls. You declare methods with @GET, @POST, @Path, @Query and @Body, and Retrofit generates the implementation using OkHttp underneath. Marking methods as suspend makes them main-safe and cancellable, returning the parsed body directly or Response<T> when you need status codes and headers. A converter like kotlinx.serialization or Moshi parses JSON.
51

Write a Retrofit interface for listing products with paging and fetching one product.

Save to ▾
Show answer
interface ShopApi { @GET("products") suspend fun getProducts( @Query("page") page: Int, @Query("size") size: Int = 20 ): ProductPageDto @GET("products/{id}") suspend fun getProduct(@Path("id") id: String): Response<ProductDto> @POST("cart") suspend fun addToCart(@Body body: AddToCartRequest): CartDto }
52

How do you check network connectivity in modern Android?

Save to ▾
Show answer
Use ConnectivityManager with registerDefaultNetworkCallback and NetworkCapabilities to check NET_CAPABILITY_INTERNET and VALIDATED, and expose it as a Flow with callbackFlow. NetworkInfo and the CONNECTIVITY_ACTION broadcast are deprecated. Remember that being connected does not guarantee a working server, so still handle request failures. Use the status to show an offline banner and pause retries, not to block every request.
53

How do you handle a situation where you are blocked by another team's API not being ready?

Save to ▾
Show answer
I agree on the API contract early, with sample JSON, and build against a fake or mock server so my UI and logic are ready. I keep the repository interface stable, so switching to the real API is a small change. I communicate status in standups and raise risks to my lead early if the dependency threatens the deadline, suggesting options like releasing behind a feature flag.
54

What types of tests do you write for an Android app?

Save to ▾
Show answer
Local unit tests on the JVM cover ViewModels, use cases, repositories and mappers with JUnit, fakes and coroutine test tools; they are fast and most numerous. Instrumented tests run on a device or emulator for Room, Compose UI and integration flows. End-to-end UI tests check critical journeys like login and checkout. Screenshot tests catch visual regressions. Follow the testing pyramid: many unit tests, fewer UI tests.
55

What is an ANR and how do you prevent it?

Save to ▾
Show answer
An ANR (Application Not Responding) happens when the main thread is blocked, for example an input event not handled within about 5 seconds or a BroadcastReceiver taking too long. Causes include disk or network work on the main thread, heavy computation, lock contention and slow SharedPreferences commits. Prevent ANRs by moving work to background dispatchers, using StrictMode in debug builds, and tracking ANR rates in Android vitals.
56

What is an Android App Bundle and why does Play require it?

Save to ▾
Show answer
An App Bundle (.aab) is a publishing format containing all compiled code and resources. The Play Store generates optimised APKs for each device configuration, delivering only the needed screen density, CPU architecture and language resources, which reduces download size. Since August 2021, new apps on Play must use AAB with Play App Signing, where the store holds the app signing key and you sign uploads with an upload key.
57

Explain the steps to publish an app on the Play Store.

Save to ▾
Show answer
Create a developer account, then an app in Play Console. Complete the store listing, content rating, data safety form, target audience, privacy policy and permissions declarations. Build a signed release AAB with a higher versionCode, upload it to internal testing first, then closed or open testing, and finally production with a staged rollout. New personal accounts must run a closed test with at least 12 testers for 14 days before production.
58

Tell me about an app or feature you are proud of building.

Save to ▾
Show answer
Choose something with clear impact. For example: I built the offline cart for our grocery app. Users in low network areas could add items without connection, and the cart synced later with conflict handling. I used Room, WorkManager and a sync status field, and wrote migration and sync tests. After release, cart abandonment from network errors dropped noticeably, and the pattern was reused for the wishlist feature.
59

Where do you see yourself in five years as an Android developer?

Save to ▾
Show answer
Keep it genuine and tied to growth. For example: in five years I want to be a senior or lead Android engineer who owns the architecture of a large app, mentors juniors and works closely with product on decisions. I plan to deepen my skills in performance, Compose and Kotlin Multiplatform, and contribute to the team's engineering practices. I hope to grow that path in a company like this one.
60

How do you handle a code review comment you disagree with?

Save to ▾
Show answer
I first assume the reviewer has a reason and ask questions to understand it. If I still disagree, I explain my reasoning with evidence, such as documentation, a benchmark or a test, and suggest a short call if comments go back and forth. If it is a matter of preference, I follow the team convention. The goal is the best code for the team, not winning the argument.

Frequently asked questions

Who should practise easy Android App Development questions?

Freshers and career switchers should start here, and experienced candidates should skim them the day before an interview.

How should I practise these?

Answer each question aloud before opening the answer, mark it as solved only when your answer matches the key idea, and save misses to Last-Minute Revision.

Other difficulty levels