Every Android app is made of screens. Each screen is an Activity. Each Activity has a Layout that describes what's on screen. And the Layout is made up of Views — buttons, text fields, images. That's the whole mental model right there.
Step 3 of the Learn Android with Kotlin series — Android Activities, Layouts and Views
Understanding how these three things connect is the foundation of everything else in Android development. Once this clicks, the rest of the series makes sense. This step explains each one, shows the Activity lifecycle that trips up almost every beginner, and builds a real login screen using ViewBinding — the modern way to access views without crashes.
1. Activities — The Entry Point for Every Screen
An Activity is a single focused screen in your app. Think of your app as a house — each room is an Activity. The front door (the one Android opens when the user taps your app icon) is your MainActivity.
Every Activity is a Kotlin class that extends AppCompatActivity:
package com.example.myfirstapp
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Links this Activity to activity_main.xml layout
setContentView(R.layout.activity_main)
}
}
Every Activity must be declared in AndroidManifest.xml. Android Studio does this automatically when you create a new Activity, but it's worth knowing:
<!-- AndroidManifest.xml -->
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<!-- This makes MainActivity the launch screen -->
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
2. The Activity Lifecycle — The Most Important Thing to Understand
Here's the thing that confuses almost every Android beginner: Android can destroy and recreate your Activity at any time — when the user rotates the phone, switches apps, or takes a phone call. If you don't understand the lifecycle, your app will lose data unexpectedly and feel broken.
The Activity Lifecycle
Android calls these methods on your Activity automatically depending on what's happening:
| Method | When it's called | What to do here |
|---|---|---|
onCreate() |
Activity is first created | Set up UI, initialise ViewBinding, set up ViewModel |
onStart() |
Activity becomes visible | Register listeners, start animations |
onResume() |
Activity is in foreground, user can interact | Resume camera, sensors, or playback |
onPause() |
Another Activity comes to foreground | Pause camera, save draft data |
onStop() |
Activity is no longer visible | Release heavy resources |
onRestart() |
Activity coming back from stopped state | Refresh data if needed |
onDestroy() |
Activity is being destroyed permanently | Clean up all resources |
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// UI setup here — runs once when Activity is created
}
override fun onResume() {
super.onResume()
// Activity is visible and interactive — good for refreshing data
}
override fun onPause() {
super.onPause()
// User is leaving — save any unsaved input here
}
override fun onDestroy() {
super.onDestroy()
// Final cleanup — release resources
}
}
onDestroy() then onCreate() again. Your Activity is completely recreated. Any variables you set in onCreate() are reset. This is exactly why we use ViewModel in Step 7 — it survives rotation so your data doesn't disappear.
3. Layouts — The Structure of Your Screen
A Layout is an XML file in res/layout/ that describes how views are arranged on screen. The layout file and the Activity are connected by setContentView(R.layout.activity_main) in onCreate().
Layout Types
| Layout | How it works | Best for |
|---|---|---|
| ConstraintLayout | Position views using constraints relative to each other and the parent | ✅ Most screens — flexible and performant |
| LinearLayout | Stack views vertically or horizontally in a line | Simple forms, vertical lists of items |
| FrameLayout | Stack views on top of each other | Fragment containers, overlays |
ConstraintLayout Example
<!-- res/layout/activity_main.xml -->
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="24dp">
<TextView
android:id="@+id/tvTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Welcome Back"
android:textSize="24sp"
android:textStyle="bold"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginTop="48dp"/>
<EditText
android:id="@+id/etEmail"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:hint="Email address"
android:inputType="textEmailAddress"
app:layout_constraintTop_toBottomOf="@id/tvTitle"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginTop="32dp"/>
<EditText
android:id="@+id/etPassword"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:hint="Password"
android:inputType="textPassword"
app:layout_constraintTop_toBottomOf="@id/etEmail"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginTop="16dp"/>
<Button
android:id="@+id/btnLogin"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Login"
app:layout_constraintTop_toBottomOf="@id/etPassword"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginTop="24dp"/>
</androidx.constraintlayout.widget.ConstraintLayout>
4. Views — The Building Blocks of Your UI
A View is a single visible element on screen. Everything the user can see or interact with is a View.
| View | Purpose | Common attributes |
|---|---|---|
TextView |
Displays text | text, textSize, textColor |
EditText |
Text input field | hint, inputType |
Button |
Tappable button | text, onClick |
ImageView |
Displays an image | src, scaleType |
CheckBox |
Toggle on/off | checked, text |
Switch |
Toggle switch | checked, text |
5. Putting It Together with ViewBinding
In Step 2 you enabled ViewBinding in your project. Now let's use it to wire the layout to your Activity code. ViewBinding generates a type-safe class from your layout — accessing the wrong view ID is a compile error, not a runtime crash.
Here's the complete login screen Activity using ViewBinding and the layout from above:
package com.example.myfirstapp
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Toast
import com.example.myfirstapp.databinding.ActivityMainBinding
class MainActivity : AppCompatActivity() {
// ViewBinding — generated from activity_main.xml
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Inflate the binding — replaces setContentView
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
// Access views via binding — no findViewById, no casting
binding.btnLogin.setOnClickListener {
val email = binding.etEmail.text.toString().trim()
val password = binding.etPassword.text.toString().trim()
if (email.isEmpty() || password.isEmpty()) {
Toast.makeText(this, "Please fill in all fields", Toast.LENGTH_SHORT).show()
return@setOnClickListener
}
if (password.length < 6) {
binding.etPassword.error = "Password must be at least 6 characters"
return@setOnClickListener
}
// Both fields valid — proceed with login
Toast.makeText(this, "Welcome, $email!", Toast.LENGTH_SHORT).show()
}
}
}
binding.btnLogin— directly typed asButton, no castingbinding.etEmail— directly typed asEditText- If you rename a view ID in the XML, all references break at compile time — not at runtime in front of a user
6. Common XML Attributes Every Beginner Needs
| Attribute | Values | Meaning |
|---|---|---|
layout_width |
match_parent, wrap_content, 0dp |
Full width, fit content, or fill constraints |
layout_height |
Same as width | Same as width |
padding |
16dp |
Space inside the view boundary |
layout_margin |
8dp |
Space outside the view boundary |
visibility |
visible, invisible, gone |
gone removes space, invisible keeps it |
gravity |
center, start, end |
How content aligns inside the view |
Try It Yourself
- Add validation — in the login screen, validate that the email contains "@" before allowing login. Use
binding.etEmail.error = "Invalid email"to show an inline error. - Add a second Activity — create
HomeActivity.ktusing New → Activity → Empty Views Activity. After a successful login, show it. (We cover navigation properly in Step 4: Intents.) - Handle rotation — type something in the email field, rotate the emulator (Ctrl + F11 on Windows / Fn + Ctrl + F11 on Mac), and notice the text disappears. We fix this with ViewModel in Step 7.
Frequently Asked Questions
What is an Activity in Android?
An Activity is a single screen — a Kotlin class extending AppCompatActivity with a linked XML layout file. Every Activity must be declared in AndroidManifest.xml. Your MainActivity is the launch screen.
What is the Activity lifecycle?
A series of methods Android calls automatically: onCreate → onStart → onResume → onPause → onStop → onDestroy. Rotating the screen triggers onDestroy then onCreate again — which is why data disappears without a ViewModel.
ConstraintLayout vs LinearLayout — which to use?
ConstraintLayout for most screens — flexible positioning, no nesting, great performance. LinearLayout for simple vertical/horizontal stacks. Avoid RelativeLayout — it's outdated and replaced by ConstraintLayout.
How do I use ViewBinding with an Activity?
Enable it in build.gradle.kts with buildFeatures { viewBinding = true }. In onCreate(): binding = ActivityMainBinding.inflate(layoutInflater) then setContentView(binding.root). Access views as binding.viewId — type-safe, no casting, compile-time safe.
- Activity = one screen, one Kotlin class, declared in
AndroidManifest.xml - Lifecycle:
onCreate → onStart → onResume → onPause → onStop → onDestroy - Rotation destroys and recreates the Activity — data disappears without ViewModel
- Layout = XML file in
res/layout/— describes the visual structure - Use ConstraintLayout for most screens — avoid RelativeLayout
- Views: TextView, EditText, Button, ImageView, CheckBox, Switch
- Use ViewBinding —
binding.viewIdinstead offindViewById() layout_width="0dp"in ConstraintLayout means "fill the constraint"- Use
view.error = "message"for inline field validation