Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 10 additions & 10 deletions src/content/study/junior/01-kotlin-foundations.md
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
---
title: Kotlin foundations for Android
description: Learn the Kotlin language features you will use before Android framework code can make sense.
title: "Kotlin: types, state, and program structure"
description: Establish the Kotlin type-system, state-modeling, and collection skills required to reason accurately about Android code.
level: junior
order: 1
duration: 50 min
quizHref: /practice/?test=kotlin-test
quizLabel: Take the Kotlin quiz
---

Kotlin is not a warm-up before “real Android.” It is how you express state, handle missing data, and prevent entire categories of mistakes in Android code. Before learning Activities or Compose, become comfortable reading and writing small Kotlin models and functions until they feel automatic.
Kotlin is the language in which an Android program states its invariants. Its type system distinguishes an absent value from a present one, its immutable bindings clarify ownership, and its algebraic types make a finite set of outcomes visible in code. These are correctness tools, not stylistic preferences.

This lesson focuses on the language surface you will touch daily: null safety, `val`/`var`, data and sealed types, functions, collections, and scope functions. Internals like variance and reified generics matter later; they are not the first gate.
This chapter establishes the language surface used throughout the curriculum: nullability, immutable state, data and sealed types, functions, collection transformations, and scope functions. Read each construct as a statement of intent. The important question is not whether code compiles, but whether another engineer can infer the permitted states and failure conditions from the type.

## Learning goals

By the end of this lesson you should be able to:

- Choose between `val` and `var`, and explain why immutability-by-default helps Android UI code.
- Handle nullable types with `?.`, `?:`, and smart casts - and know when `!!` is a smell.
- Model a screen’s data with `data class` and mutually exclusive outcomes with `sealed interface` / `sealed class`.
- Transform collections with `map`, `filter`, `firstOrNull`, and `associateBy` without hiding business rules.
- Pick a scope function (`let`, `also`, `apply`, `run`, `with`) for a clear purpose, or refuse one when it hurts readability.
- Choose between `val` and `var` by considering reference reassignment and mutation separately.
- Handle nullable values with `?.`, `?:`, and smart casts, and identify the exact failure condition introduced by `!!`.
- Model screen data with `data class` and mutually exclusive outcomes with `sealed interface` or `sealed class`.
- Transform collections with `map`, `filter`, `firstOrNull`, and `associateBy` without concealing a business rule in a chain.
- Select a scope function only when its receiver, return value, and purpose remain clear to the reader.

## Values, variables, and nullability

Expand Down Expand Up @@ -239,7 +239,7 @@ val label = when (val code = response.code) {
4. **Boolean soup** for UI (`isLoading && !hasError && data != null`) instead of a sealed state.
5. **Scope-function noise** that makes a simple block unreadable under interview pressure.

## How interviewers probe this
## Examination prompts

Expect:

Expand Down
18 changes: 9 additions & 9 deletions src/content/study/junior/02-activities.md
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
---
title: "Activities: an Android screen's entry point"
description: Understand what an Activity owns, how Android creates it, and why it should stay thin.
title: Activities, intents, tasks, and window ownership
description: Understand how the system creates an Activity, delivers input, manages tasks, and defines the boundary of a screen host.
level: junior
order: 2
duration: 45 min
quizHref: /practice/?test=android-fundamentals-test
quizLabel: Take the fundamentals quiz
---

An **Activity** is an Android component that provides a window where your app can show a screen. Android creates it in response to an explicit intent, a launcher tap, a deep link, or task restoration. Your code does not call an Activity constructor as the normal entry path. The operating system controls its lifecycle and may create a new instance when you did not expect it - after rotation, locale change, or process death recovery.
An **Activity** is an Android application component that owns a window and participates in the system task model. The operating system, not ordinary application code, creates it in response to a launcher action, an explicit intent, a verified link, or restoration of a task. That ownership explains why an Activity instance is replaceable and why it is an unsuitable home for durable business state.

Modern apps often use a **single-Activity** architecture: one Activity hosts many Compose destinations or Fragments. Even then, you must understand what that Activity owns, how intents deliver data, and how tasks and the back stack work.
Many modern applications use one Activity to host a navigation system. The architecture does not remove the Activity contract. A screen host must still accept and validate external input, configure the window, coordinate system callbacks, and leave data loading and business decisions to longer-lived collaborators.

## Learning goals

- Explain what an Activity is responsible for - and what it should not own.
- Trace how an intent starts an Activity and how extras are read safely.
- Describe tasks, the back stack, and common launch-mode pitfalls at a junior level.
- Keep Activities thin: theme, content, navigation host, system callbacks - not network or business rules.
- Define the window-scoped responsibilities of an Activity and identify work that belongs elsewhere.
- Trace an intent from component resolution to validated arguments.
- Describe a task, its back stack, and the consequences of common launch modes.
- Keep the Activity limited to theme, content, navigation host, and system callbacks rather than network or business rules.

## What an Activity is

Expand Down Expand Up @@ -222,7 +222,7 @@ You may still use multiple Activities for separate tasks (e.g. a picture-in-pict
4. **Assuming `onCreate` runs for every intent** - false for `onNewIntent` cases.
5. **Putting business logic in the Activity** so unit tests require Robolectric or instrumentation for no good reason.

## How interviewers probe this
## Examination prompts

- “What is an Activity?” - component + window + system-managed lifecycle.
- “Difference between explicit and implicit intents?”
Expand Down
20 changes: 9 additions & 11 deletions src/content/study/junior/03-fragments.md
Original file line number Diff line number Diff line change
@@ -1,25 +1,23 @@
---
title: Fragments and view lifecycle
description: Learn why a Fragment can outlive its view and how that changes safe UI code.
title: Fragments and the view-lifecycle boundary
description: Learn the separate lifetimes of a Fragment and its view, then apply that distinction to bindings, observers, and navigation.
level: junior
order: 3
duration: 45 min
quizHref: /practice/?test=android-fundamentals-test
quizLabel: Take the fundamentals quiz
---

A **Fragment** represents a reusable portion of UI or navigation within an Activity. It has its own lifecycle, but the critical detail juniors miss is that its **view has a different lifecycle**. A Fragment can remain on the back stack while Android destroys its view to free memory. Later, the same Fragment instance can create a **new** view.
A **Fragment** is a controller that can contribute UI and navigation to an Activity. Its instance lifecycle and its view lifecycle are deliberately different. A Fragment may remain in the FragmentManager while its view hierarchy is destroyed, then create a replacement hierarchy later. Every safe Fragment implementation begins by treating those two lifetimes as separate ownership domains.

If you hold a `View` / View Binding / RecyclerView reference past `onDestroyView`, you leak memory and can crash when you touch a dead view hierarchy.

Even if your app is Compose-first and “never uses Fragments,” interviewers still ask about them. Navigation, ViewPager, and many production codebases still depend on Fragment semantics - especially the view-lifecycle gap.
A `View`, View Binding, adapter connected to views, or observer that updates views belongs to the view lifecycle. Retaining one after `onDestroyView` keeps the obsolete hierarchy reachable and can produce a memory leak or a stale UI update. This distinction remains important in Compose-first applications because established applications, ViewPager integrations, and navigation hosts commonly retain Fragment boundaries.

## Learning goals

- Separate **Fragment lifecycle** from **view lifecycle**.
- Create and clear view bindings correctly.
- Observe LiveData / collect flows with `viewLifecycleOwner`, not `this` (the Fragment).
- Explain when Fragments still matter in a Compose world.
- Separate the Fragment instance lifecycle from the lifecycle of its current view hierarchy.
- Create and clear a View Binding at the correct boundary.
- Observe LiveData and collect UI streams with `viewLifecycleOwner`, not the Fragment instance.
- Explain when Fragment semantics remain relevant in a Compose-based application.

## Fragment vs view lifecycle

Expand Down Expand Up @@ -217,7 +215,7 @@ Do not store UI state only in view fields (`binding.title.text`) if it must retu
5. **Retaining large objects (bitmaps, adapters) on the Fragment instance** across `onDestroyView`.
6. **Nested Fragments with the wrong FragmentManager** (`parent` vs `child`).

## How interviewers probe this
## Examination prompts

- “Difference between Fragment lifecycle and view lifecycle?”
- “Why `viewLifecycleOwner`?”
Expand Down
18 changes: 9 additions & 9 deletions src/content/study/junior/04-lifecycle.md
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
---
title: Lifecycle, configuration change, and process death
description: Know what Android preserves, what it recreates, and where important state belongs.
title: Lifecycle, recreation, and durable state
description: Classify configuration change and process death correctly, then place UI state and durable data in the owner that can recover it.
level: junior
order: 4
duration: 50 min
quizHref: /practice/?test=android-fundamentals-test
quizLabel: Take the fundamentals quiz
---

**Lifecycle** is the contract between your UI and Android. The system can pause your app when another window appears, stop it when it is no longer visible, destroy an Activity for a configuration change, or kill the whole process to reclaim memory. Correct Android code treats these as **normal events**, not exceptional failures.
Lifecycle is Android's contract for changing ownership. The system can obscure a window, stop a component, recreate an Activity for a configuration change, or reclaim the entire process. These are ordinary operating conditions. An application that treats them as rare errors eventually loses state, leaks resources, or repeats work.

Juniors who only memorize callback names struggle. Juniors who ask “what ownership changes here?” and “what state still exists?” do well in interviews and in production.
Do not memorize callback names in isolation. At each lifecycle boundary, determine what remains visible, which object is being replaced, which work must stop, and which data must survive without relying on a final callback. That model provides a reliable answer for both View and Compose applications.

## Learning goals

- Trace Activity lifecycle callbacks and what each implies for resources and UI.
- Distinguish **configuration change** from **process death**.
- Place state in the right store: UI widget, ViewModel, SavedStateHandle, or durable storage.
- Collect flows and start work in a lifecycle-aware way (`repeatOnLifecycle`, `WhenStarted`, etc.).
- Trace Activity lifecycle callbacks and the resource or UI obligation each one implies.
- Distinguish configuration recreation from process death.
- Place state in a widget, ViewModel, `SavedStateHandle`, or durable storage according to its required lifetime.
- Collect streams and start UI work with lifecycle-aware APIs such as `repeatOnLifecycle`.

## The core Activity callbacks

Expand Down Expand Up @@ -222,7 +222,7 @@ Never rely on `onDestroy` as the only place to persist user data.
4. **Updating UI after `onDestroyView` / destroyed lifecycle.**
5. **Assuming `init` in ViewModel runs once per app** - it runs once per ViewModel instance; process death creates a new one.

## How interviewers probe this
## Examination prompts

- Walk through rotation with a form draft in different storage locations.
- “Does ViewModel survive process death?” - **No** (in-memory); SavedStateHandle can restore small keys.
Expand Down
20 changes: 9 additions & 11 deletions src/content/study/junior/05-ui-state.md
Original file line number Diff line number Diff line change
@@ -1,25 +1,23 @@
---
title: UI state and UI models
description: Model what a screen can show before wiring network calls or rendering components.
title: UI state, events, and rendering models
description: Model the valid states of a screen, distinguish state from one-time work, and map application data into renderable UI models.
level: junior
order: 5
duration: 50 min
quizHref: /practice/?test=architecture-test
quizLabel: Take the architecture quiz
---

A screen is easiest to build when you can describe its **state** before writing widgets or firing network calls. Avoid several unrelated flags such as `isLoading`, `hasError`, and `showContent`. Those flags can contradict one another: is the screen loading *and* showing content? Is the error blocking, or a small refresh warning over cached data?
A screen should be specified as a set of states before it is rendered as widgets. Independent flags such as `isLoading`, `hasError`, and `showContent` permit contradictory combinations and leave the renderer to invent product policy. A state model should instead make every meaningful condition explicit, including cached content that is refreshing and an error that does not block existing data.

**UI models** are the data the UI needs to render - not the Retrofit DTO, not the Room entity, not the domain object with twenty unused fields. Mapping into UI models forces you to decide what the user actually sees.

This is the last junior lesson before mid-level async and architecture work. Master it here; everything later assumes it.
**UI models** describe the information and actions required to render a particular surface. They are neither transport DTOs nor database entities. Mapping to a UI model is a design step: it decides what the user can see, what is unavailable, and what action is possible. This model is the foundation for the asynchronous and architectural work that follows.

## Learning goals

- Replace boolean soup with explicit, valid states.
- Separate **state** (what is true now) from **events** (one-off things that must happen once).
- Design `*UiModel` / `*UiState` types the UI can render without guessing.
- Place state in the right owner (composable memory, ViewModel, disk).
- Replace unrelated flags with a state model that represents only valid combinations.
- Separate present state from an action that must occur once.
- Design `*UiModel` and `*UiState` types that the renderer can consume without inference.
- Place state in composable memory, a ViewModel, or durable storage according to its required lifetime.

## Make valid states explicit

Expand Down Expand Up @@ -306,7 +304,7 @@ list.add(newItem)
_state.update { it.copy(items = it.items + newItem) }
```

## How interviewers probe this
## Examination prompts

- “How do you model loading / content / error?”
- “Difference between UI state and one-off events?”
Expand Down
20 changes: 10 additions & 10 deletions src/content/study/junior/06-context-resources-and-process.md
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
---
title: Context, resources, and the Android process
description: Understand what Context gives you, how Android selects resources, and which objects must never be kept alive accidentally.
title: Context, resources, process lifetime, and memory ownership
description: Choose the correct Android Context, predict resource resolution, and prevent leaks by matching every reference to its proper lifetime.
level: junior
order: 6
duration: 55 min
quizHref: /practice/?test=android-fundamentals-test
quizLabel: Take the Android fundamentals quiz
---

`Context` is one of the most frequently passed objects in Android and one of the least precisely explained. It is not simply "the app." A `Context` is an interface to environment-specific services and resources. The environment may be an `Activity`, the application, a service, or a wrapped context with a different theme or configuration.
`Context` is an interface to services, resources, package operations, and configuration that belong to a particular Android environment. It is not a synonym for the application. An Activity, an application, a service, and a themed wrapper provide different capabilities, themes, configurations, and lifetimes.

This distinction matters because the object you choose controls what is available, which theme is used, and how long a reference can safely live.
Selecting the wrong Context can be a functional defect as well as a memory defect. A dialog needs an Activity-backed themed context; a long-lived cache should not retain that Activity. Resource selection and process lifetime rely on the same discipline: identify the environment and lifetime before retaining or resolving anything.

## Learning goals

- Explain what `Context` provides without calling it a global variable.
- Choose an `Activity` context or application context based on lifetime and capability.
- Read resource qualifiers and predict which resource Android selects.
- Distinguish an app process from an Activity, task, and application object.
- Find common memory leaks caused by long-lived references.
- Explain the capabilities supplied by a Context without treating it as a global variable.
- Choose an Activity or application Context from the operation's capability and lifetime requirements.
- Read resource qualifiers and predict the selected resource.
- Distinguish a process from an Activity, task, and Application object.
- Identify memory leaks caused by retaining a reference beyond the owner's lifetime.

## What `Context` actually provides

Expand Down Expand Up @@ -228,7 +228,7 @@ The useful interview rule is: **compare the lifetime of the owner with the lifet
6. Assuming a hardware feature exists because an API exists.
7. Doing heavy initialization in `Application.onCreate()`.

## How interviewers probe this
## Examination prompts

- "What is Context?"
- "Application context vs Activity context?"
Expand Down
Loading