Quick Answer

Learn Kotlin, then Jetpack Compose for the UI, and understand the activity lifecycle. Android Studio is the only realistic development environment. XML layouts and Java are legacy for new projects.

The current stack, and what is legacy

This matters more in Android than most platforms, because search results are full of superseded approaches.

Current: Kotlin as the language, Jetpack Compose for the UI, coroutines and Flow for asynchronous work, ViewModel for state that survives configuration changes, Room for local storage, and Hilt for dependency injection.

Legacy but still widespread: Java, XML layouts with findViewById, AsyncTask (deprecated), Fragments in the old style, and RxJava.

You will meet the legacy stack in existing codebases and in most tutorials written before about 2022. Do not start there. Compose is a genuinely different model, and learning XML layouts first does not help you learn it — it competes with it.

See Kotlin for Java developers; Kotlin is effectively mandatory now, since Compose is Kotlin-only.

Compose: describing the UI as a function of state

@Composable
fun Counter() {
    var count by remember { mutableStateOf(0) }

    Column(modifier = Modifier.padding(16.dp)) {
        Text("Count: $count", style = MaterialTheme.typography.headlineMedium)
        Button(onClick = { count++ }) {
            Text("Increment")
        }
    }
}

If that looks like React, that is not a coincidence — it is the same declarative idea. You describe what the UI should look like for the current state, and the framework works out the updates.

The old approach was imperative: define a layout in XML, find views by ID, and mutate them. That meant the UI could drift out of sync with your data, which is the source of a large class of Android bugs.

Two things to understand early. remember keeps a value across recompositions — without it, state resets every time the function re-runs. And Modifier is how you apply padding, size, click handling and background, chained in order, where order matters: padding then background gives a different result from background then padding.

The lifecycle, which causes the classic bugs

An Activity is a screen, and Android controls its life aggressively. It can destroy and recreate your screen at any time — most commonly on rotation, but also on language change, dark mode toggle, or when the system needs memory.

The classic beginner bug: enter data, rotate the phone, everything is gone. The activity was destroyed and recreated, and your state lived in it.

The fix is ViewModel, which survives configuration changes:

class StudentViewModel : ViewModel() {
    private val _students = MutableStateFlow<List<Student>>(emptyList())
    val students = _students.asStateFlow()

    fun load() {
        viewModelScope.launch {
            _students.value = repository.fetch()
        }
    }
}

viewModelScope also cancels running coroutines when the ViewModel is cleared, which prevents the other classic bug: a network response arriving after the screen is gone and crashing on a null reference.

The rule that avoids most of this: UI holds no state, ViewModel holds state, and the UI observes it.

The practical realities

  • Android Studio is required in practice. It is heavy — budget 8 GB of RAM minimum, 16 GB to be comfortable. The emulator is the main resource consumer.
  • Test on a real device. Enable developer options and USB debugging. The emulator hides performance problems and does not reproduce real-device quirks, which are numerous on Android.
  • Gradle builds are slow and this is a known frustration. Enable the build cache and configuration cache.
  • Fragmentation is real. Your app runs on many Android versions, screen sizes and manufacturer skins. Set minSdk deliberately; supporting very old versions costs real effort.
  • Permissions are requested at runtime and can be denied or revoked. Handle the denial path — an app that crashes when camera access is refused is a common review complaint.

A sensible learning path

In order, without skipping:

  1. Kotlin fundamentals — classes, null safety, collections, lambdas. A week or two.
  2. One screen in Compose with state and a button. Understand recomposition and remember.
  3. Lists and navigationLazyColumn and moving between screens.
  4. Network calls with Retrofit plus coroutines, displaying real data with loading and error states.
  5. Local storage with Room, so the app works offline.
  6. ViewModel and architecture, tying it together properly.

Build one complete small app rather than following six tutorials. An app that fetches data, caches it, handles errors and survives rotation demonstrates more than a longer feature list — and those four things are exactly what interviewers probe.

If you are also considering cross-platform, see React Native vs Flutter.

Frequently Asked Questions

Should I learn Java or Kotlin for Android? Kotlin. It is Google's preferred language, new libraries are Kotlin-first, and Jetpack Compose is Kotlin-only. Java remains only in existing codebases.
Why does my app lose data when I rotate the phone? Rotation destroys and recreates the activity. Hold state in a ViewModel, which survives configuration changes, rather than in the activity or composable.
Should I learn XML layouts or Compose? Compose for new work. XML layouts are legacy, and learning them first does not help with Compose because the models are fundamentally different.
Do I need a powerful computer for Android development? Android Studio and the emulator are demanding — 8 GB of RAM is a realistic minimum and 16 GB is comfortable. Testing on a physical device reduces the emulator burden.
How long does it take to build a first app? With Kotlin basics in place, a simple app that fetches and displays data is realistic within a few weeks. Handling offline storage, errors and lifecycle properly takes longer and matters more.