Knowledge / Computer Applications / Android app development with Kotlin

Android app development with Kotlin

Computer Applications (MCA) · Mobile, cloud and data · free study notes for exams, placements and interviews

In short

Android app development with Kotlin is the building of applications for the Android operating system using Kotlin, the statically typed JVM language that Google declared "Kotlin-first" for Android in 2019 and which is now the default language of Android Studio templates. A student must know Kotlin's language features (null safety, data classes, coroutines), the Android component model (Activity, Service, BroadcastReceiver, ContentProvider), lifecycle handling, UI with XML layouts and Jetpack Compose, local storage with Room, and networking with Retrofit. The topic carries heavy weight in MCA mobile-computing papers, in lab vivas and in placement rounds at Indian product and services firms — Flipkart, Swiggy, Zomato, Paytm, PhonePe, Razorpay, Jio, Zoho, TCS, Infosys, Accenture — where Android questions are usually lifecycle, memory-leak and coroutine-concurrency questions in disguise. India's large Android user base (the overwhelming majority of smartphones here run Android) means almost every Indian consumer product ships an Android app first.

Explained

Kotlin language essentials examined in Android papers

Android platform architecture and components

Lifecycles — the most examined area

Concurrency with coroutines

UI: XML views and Jetpack Compose

Architecture, data layer and dependency injection

Build, testing, release and Indian compliance

Key points

Formulas and examples

dp → px: px = dp × (dpi / 160) — equivalently px = dp × density; density = dpi/160 (mdpi = 1.0, hdpi = 1.5, xhdpi = 2.0, xxhdpi = 3.0)
Screen density dpi = √(wₚₓ² + hₚₓ²) / diagonal_in_inches
APK/bundle size budget: total download ≈ Σ(DEX) + Σ(resources after density split) + native libs per ABI
Version code convention: versionCode = major×10000 + minor×100 + patch (a single increasing integer Play uses to order builds)
Smallest-width qualifier: a layout in res/layout-sw600dp applies when min(widthDp, heightDp) ≥ 600dp, where widthDp = widthPx × 160 / dpi
Coroutine timing: sequential total ≈ Σtᵢ; with async/await in parallel, total ≈ max(tᵢ) + overhead

Example 1 — dp to px on three Indian handsets. A button is specified 48 dp tall (the Material minimum touch target).

Same physical size (48/160 = 0.3 inch ≈ 7.6 mm) on every device — which is the whole point of dp.

Example 2 — density bucket and tablet layout decision. A phone is 1080 × 2400 px on a 6.5-inch diagonal.

Example 3 — parallel vs sequential coroutines. A dashboard needs profile (300 ms), orders (500 ms) and offers (400 ms) from three endpoints.

// Sequential: 300 + 500 + 400 = 1200 ms
val p = api.profile(); val o = api.orders(); val f = api.offers()

// Parallel: bounded by the slowest call
suspend fun load() = coroutineScope {
    val p = async { api.profile() }   // 300 ms
    val o = async { api.orders() }    // 500 ms
    val f = async { api.offers() }    // 400 ms
    Dashboard(p.await(), o.await(), f.await())   // ≈ 500 ms
}

Example 4 — ViewModel + StateFlow + Room, a complete vertical slice.

@Entity(tableName = "orders")
data class Order(
    @PrimaryKey val id: String,
    val amountPaise: Long,          // store money in paise, never Double
    val placedAt: Long
)

@Dao
interface OrderDao {
    @Query("SELECT * FROM orders ORDER BY placedAt DESC")
    fun observeAll(): Flow<List<Order>>

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun upsert(orders: List<Order>)
}

sealed interface OrdersUiState {
    data object Loading : OrdersUiState
    data class Success(val orders: List<Order>, val totalRupees: String) : OrdersUiState
    data class Error(val message: String) : OrdersUiState
}

@HiltViewModel
class OrdersViewModel @Inject constructor(
    private val repo: OrderRepository
) : ViewModel() {

    val state: StateFlow<OrdersUiState> = repo.observeOrders()
        .map { list ->
            val paise = list.sumOf { it.amountPaise }
            OrdersUiState.Success(list, "₹%.2f".format(paise / 100.0))
        }
        .catch { emit(OrdersUiState.Error(it.message ?: "Unknown error")) }
        .stateIn(viewModelScope, SharingStarted.WhileSubscribed(5_000), OrdersUiState.Loading)

    fun refresh() = viewModelScope.launch {
        withContext(Dispatchers.IO) { repo.syncFromNetwork() }   // Retrofit suspend call
    }
}

@Composable
fun OrdersScreen(vm: OrdersViewModel = hiltViewModel()) {
    val state by vm.state.collectAsStateWithLifecycle()
    when (val s = state) {
        OrdersUiState.Loading -> CircularProgressIndicator()
        is OrdersUiState.Error -> Text(s.message)
        is OrdersUiState.Success -> LazyColumn {
            items(s.orders, key = { it.id }) { Text("${it.id} — ${s.totalRupees}") }
        }
    }
}

Example 5 — release size after R8. A debug build is 18.4 MB; R8 shrinking removes 42% of DEX and resource shrinking removes 30% of a 6.0 MB resource set; DEX was 9.0 MB, native libs 3.4 MB for two ABIs.

AspectXML ViewsJetpack Compose
ParadigmImperative — inflate then mutate viewsDeclarative — UI = f(state)
ListsRecyclerView + Adapter + DiffUtilLazyColumn with key
State restoreonSaveInstanceState, ViewModelrememberSaveable, ViewModel
Stylingthemes/styles XML, Material componentsMaterial 3 theming in Kotlin
BoilerplateHigh (adapters, bindings)Low
InteropHosts Compose via ComposeViewHosts views via AndroidView
ConcernLiveDataStateFlowSharedFlow
LibraryAndroid-only (lifecycle)Pure Kotlin coroutinesPure Kotlin coroutines
Initial valueOptional (may be null)MandatoryNone
Lifecycle awarenessBuilt inNeeds collectAsStateWithLifecycle / repeatOnLifecycleSame
ConflationLatest value onlyLatest value, distinct-until-changedConfigurable replay
Best forLegacy code, Java interopScreen stateOne-shot events (toast, navigation)
Storage optionUse forNotes
DataStore (Preferences)Small key-value settingsCoroutine/Flow API; replaces SharedPreferences
RoomStructured relational dataCompile-time SQL checks, Flow queries, migrations
Internal filesApp-private filesAuto-deleted on uninstall, no permission needed
MediaStore / SAFUser media and documentsScoped storage; no broad file permission
EncryptedSharedPreferences / KeystoreTokens, keysHardware-backed keys where available

Where it is used

Interview questions

Common mistakes

Related topics

Cross-platform apps: Flutter and React Native · Object-oriented programming in Java · RESTful web services and API design · SQL and relational database design · Software architecture and design patterns · Information security fundamentals

Open in the Knowledge reader →Find jobs →