Bird
Raised Fist0
Android Kotlinmobile~20 mins

Room database setup in Android Kotlin - Mini App: Build & Ship

Choose your learning style10 modes available
Build: User List
This screen shows a list of users stored in a local Room database. Users can be added and retrieved from the database.
Target UI
---------------------
| User List         |
|-------------------|
| + Add User        |
|                   |
| [List of users]   |
|                   |
---------------------
Set up Room database with an Entity called User with fields: id (auto-generated), name (String), and age (Int).
Create a DAO interface with methods to insert a user and get all users.
Create the Room database class.
In the main activity, display the list of users from the database.
Add a FloatingActionButton to add a new user with a fixed name and age for simplicity.
Starter Code
Android Kotlin
package com.example.roomsetup

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.launch

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            // TODO: Add UI and database code here
        }
    }
}

// TODO: Define User entity

// TODO: Define UserDao interface

// TODO: Define AppDatabase abstract class
Task 1
Task 2
Task 3
Task 4
Task 5
Task 6
Solution
Android Kotlin
package com.example.roomsetup

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.lifecycle.lifecycleScope
import androidx.room.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext

@Entity
data class User(
    @PrimaryKey(autoGenerate = true) val id: Int = 0,
    val name: String,
    val age: Int
)

@Dao
interface UserDao {
    @Insert
    suspend fun insert(user: User)

    @Query("SELECT * FROM User")
    suspend fun getAll(): List<User>
}

@Database(entities = [User::class], version = 1)
abstract class AppDatabase : RoomDatabase() {
    abstract fun userDao(): UserDao
}

class MainActivity : ComponentActivity() {
    private lateinit var db: AppDatabase

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        db = Room.databaseBuilder(
            applicationContext,
            AppDatabase::class.java, "user-database"
        ).build()

        setContent {
            var users by remember { mutableStateOf<List<User>>(emptyList()) }

            LaunchedEffect(Unit) {
                users = withContext(Dispatchers.IO) { db.userDao().getAll() }
            }

            Scaffold(
                floatingActionButton = {
                    FloatingActionButton(onClick = {
                        lifecycleScope.launch {
                            withContext(Dispatchers.IO) {
                                db.userDao().insert(User(name = "John Doe", age = 30))
                            }
                            users = withContext(Dispatchers.IO) { db.userDao().getAll() }
                        }
                    }) {
                        Text("+")
                    }
                }
            ) { paddingValues ->
                Column(modifier = androidx.compose.ui.Modifier.padding(paddingValues)) {
                    Text("User List", style = MaterialTheme.typography.headlineMedium, modifier = androidx.compose.ui.Modifier.padding(16.dp))
                    LazyColumn {
                        items(users) { user ->
                            Text(text = "${user.name}, Age: ${user.age}", modifier = androidx.compose.ui.Modifier.padding(8.dp))
                        }
                    }
                }
            }
        }
    }
}

We defined a User data class as an Entity with an auto-generated primary key. The UserDao interface has methods to insert a user and get all users. The AppDatabase class extends RoomDatabase and provides access to the DAO.

In MainActivity, we build the database instance. We use Compose to display the list of users in a LazyColumn. A floating action button inserts a new user with fixed data when clicked, then reloads the list from the database.

This setup shows how to connect Room database with UI and perform basic insert and query operations.

Final Result
Completed Screen
---------------------
| User List         |
|-------------------|
| + Add User        |
|                   |
| John Doe, Age: 30 |
| John Doe, Age: 30 |
| ...               |
---------------------
Tapping the '+' button adds a new user named 'John Doe' aged 30 to the list.
The list updates immediately to show all users stored in the database.
Stretch Goal
Add a dialog to input user name and age instead of fixed values.
💡 Hint
Use Compose AlertDialog with TextFields to get user input, then insert the new user with entered data.

Practice

(1/5)
1. What is the main purpose of the @Entity annotation in Room database setup?
easy
A. To define a table in the database
B. To create a database instance
C. To write SQL queries
D. To start a database transaction

Solution

  1. Step 1: Understand the role of @Entity

    The @Entity annotation marks a Kotlin data class as a table in the Room database.
  2. Step 2: Differentiate from other annotations

    Other annotations like @Dao define data access objects, not tables.
  3. Final Answer:

    To define a table in the database -> Option A
  4. Quick Check:

    @Entity = Table definition [OK]
Hint: Remember: @Entity means table in Room [OK]
Common Mistakes:
  • Confusing @Entity with @Dao
  • Thinking @Entity creates the database
  • Mixing @Entity with SQL query annotations
2. Which of the following is the correct way to declare a Room database class in Kotlin?
easy
A. @Dao(entities = [User::class], version = 1)\ninterface AppDatabase {\n fun userDao(): UserDao\n}
B. @Database(entities = [User::class], version = 1)\nabstract class AppDatabase : RoomDatabase() {\n abstract fun userDao(): UserDao\n}
C. @Entity(entities = [User::class], version = 1)\nclass AppDatabase : RoomDatabase() {\n fun userDao(): UserDao\n}
D. @Database(entities = User, version = 1)\nclass AppDatabase() {\n fun userDao(): UserDao\n}

Solution

  1. Step 1: Identify correct annotation and class type

    The Room database class must be annotated with @Database and extend RoomDatabase.
  2. Step 2: Check syntax for entities and abstract DAO method

    The entities list must be an array of classes, and DAO methods must be abstract.
  3. Final Answer:

    @Database(entities = [User::class], version = 1)\nabstract class AppDatabase : RoomDatabase() {\n abstract fun userDao(): UserDao\n} -> Option B
  4. Quick Check:

    @Database + abstract class + extends RoomDatabase = correct [OK]
Hint: Database class is abstract and annotated @Database [OK]
Common Mistakes:
  • Using @Entity instead of @Database
  • Not making the class abstract
  • Forgetting to extend RoomDatabase
3. Given the following code snippet, what will be the result of calling db.userDao().getAllUsers()?
@Dao
interface UserDao {
  @Query("SELECT * FROM user")
  fun getAllUsers(): List<User>
}

@Entity
data class User(
  @PrimaryKey val id: Int,
  val name: String
)

// Assume database is properly created and contains 3 users
medium
A. A runtime error because of missing suspend keyword
B. An empty list
C. A list of 3 User objects from the database
D. A compilation error due to missing @Insert method

Solution

  1. Step 1: Understand the DAO query

    The @Query("SELECT * FROM user") fetches all rows from the user table.
  2. Step 2: Check the database state

    The question states the database contains 3 users, so the query returns 3 User objects.
  3. Final Answer:

    A list of 3 User objects from the database -> Option C
  4. Quick Check:

    Query returns all users = 3 users [OK]
Hint: Query returns all rows; count matches stored data [OK]
Common Mistakes:
  • Assuming empty list without data check
  • Confusing suspend functions with normal DAO methods
  • Expecting errors without code context
4. Identify the error in this Room database builder code snippet:
val db = Room.databaseBuilder(
  context,
  AppDatabase::class.java,
  "app_db"
).build()
medium
A. Missing fallbackToDestructiveMigration() causing crash on schema change
B. Incorrect database name format, should be a URI
C. AppDatabase must be an interface, not a class
D. databaseBuilder requires a coroutine scope parameter

Solution

  1. Step 1: Review databaseBuilder usage

    The code correctly builds the database but lacks migration strategy.
  2. Step 2: Understand migration impact

    Without fallbackToDestructiveMigration(), schema changes cause runtime crashes.
  3. Final Answer:

    Missing fallbackToDestructiveMigration() causing crash on schema change -> Option A
  4. Quick Check:

    Missing migration fallback = crash risk [OK]
Hint: Add fallbackToDestructiveMigration() to avoid crashes [OK]
Common Mistakes:
  • Thinking database name must be URI
  • Confusing class vs interface for database
  • Expecting coroutine scope in builder
5. You want to add a new column age to your existing User entity without losing existing data. Which approach correctly updates the Room database?
hard
A. Change the database name to force a new database creation
B. Just add the new field in the User class and keep the same database version
C. Delete the app data and reinstall to reset the database
D. Increase database version and provide a migration object with SQL to add the new column

Solution

  1. Step 1: Understand schema changes in Room

    Adding a new column changes the database schema, so version must increase.
  2. Step 2: Provide migration to preserve data

    Migration object with SQL ALTER TABLE adds the column without losing data.
  3. Final Answer:

    Increase database version and provide a migration object with SQL to add the new column -> Option D
  4. Quick Check:

    Schema change needs version bump + migration [OK]
Hint: Always migrate with version bump to keep data safe [OK]
Common Mistakes:
  • Changing entity without version update
  • Deleting app data instead of migrating
  • Changing database name to avoid migration
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard