0
0
Android Kotlinmobile~20 mins

Room queries (Insert, Update, Delete, Select) in Android Kotlin - Mini App: Build & Ship

Choose your learning style9 modes available
Build: Simple Notes
A screen to add, update, delete, and view notes using Room database queries.
Target UI
-------------------------
| Simple Notes          |
-------------------------
| [Enter note here]     |
| [Save] [Update]       |
|-----------------------|
| Notes List:           |
| 1. Note one           |
| 2. Note two           |
| ...                   |
-------------------------
Use Room database with an Entity called Note with fields id (auto-generated) and text.
Implement DAO with insert, update, delete, and select all queries.
Screen has an EditText to enter note text.
Save button inserts a new note.
Update button updates the selected note.
Display all notes in a scrollable list.
Tapping a note loads it into the EditText for editing.
Delete a note by long-pressing it.
Starter Code
Android Kotlin
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.room.*

@Entity
 data class Note(
  @PrimaryKey(autoGenerate = true) val id: Int = 0,
  val text: String
)

@Dao
interface NoteDao {
  // TODO: Add insert, update, delete, and select queries here
}

@Database(entities = [Note::class], version = 1)
abstract class AppDatabase : RoomDatabase() {
  abstract fun noteDao(): NoteDao
}

class MainActivity : ComponentActivity() {
  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    val db = Room.databaseBuilder(
      applicationContext,
      AppDatabase::class.java, "notes-db"
    ).build()
    val noteDao = db.noteDao()

    setContent {
      // TODO: Build UI with EditText, Save, Update buttons, and notes list
    }
  }
}
Task 1
Task 2
Task 3
Task 4
Task 5
Task 6
Task 7
Solution
Android Kotlin
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.unit.dp
import androidx.room.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext

@Entity
 data class Note(
  @PrimaryKey(autoGenerate = true) val id: Int = 0,
  val text: String
)

@Dao
interface NoteDao {
  @Insert
  suspend fun insert(note: Note): Long

  @Update
  suspend fun update(note: Note)

  @Delete
  suspend fun delete(note: Note)

  @Query("SELECT * FROM Note ORDER BY id DESC")
  suspend fun getAll(): List<Note>
}

@Database(entities = [Note::class], version = 1)
abstract class AppDatabase : RoomDatabase() {
  abstract fun noteDao(): NoteDao
}

class MainActivity : ComponentActivity() {
  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    val db = Room.databaseBuilder(
      applicationContext,
      AppDatabase::class.java, "notes-db"
    ).build()
    val noteDao = db.noteDao()

    setContent {
      val scope = rememberCoroutineScope()
      var notes by remember { mutableStateOf(listOf<Note>()) }
      var currentNoteId by remember { mutableStateOf<Int?>(null) }
      var noteText by remember { mutableStateOf("") }

      LaunchedEffect(Unit) {
        notes = withContext(Dispatchers.IO) { noteDao.getAll() }
      }

      fun refreshNotes() {
        scope.launch {
          notes = withContext(Dispatchers.IO) { noteDao.getAll() }
        }
      }

      Scaffold(
        topBar = {
          CenterAlignedTopAppBar(title = { Text("Simple Notes") })
        },
        content = { padding ->
          Column(
            modifier = Modifier
              .padding(padding)
              .padding(16.dp)
          ) {
            OutlinedTextField(
              value = noteText,
              onValueChange = { noteText = it },
              label = { Text("Enter note here") },
              modifier = Modifier.fillMaxWidth()
            )
            Spacer(modifier = Modifier.height(8.dp))
            Row {
              Button(onClick = {
                if (noteText.isNotBlank()) {
                  scope.launch {
                    withContext(Dispatchers.IO) {
                      noteDao.insert(Note(text = noteText))
                    }
                    noteText = ""
                    currentNoteId = null
                    refreshNotes()
                  }
                }
              }) {
                Text("Save")
              }
              Spacer(modifier = Modifier.width(8.dp))
              Button(onClick = {
                val id = currentNoteId
                if (id != null && noteText.isNotBlank()) {
                  scope.launch {
                    withContext(Dispatchers.IO) {
                      noteDao.update(Note(id = id, text = noteText))
                    }
                    noteText = ""
                    currentNoteId = null
                    refreshNotes()
                  }
                }
              }) {
                Text("Update")
              }
            }
            Spacer(modifier = Modifier.height(16.dp))
            Text("Notes List:", style = MaterialTheme.typography.titleMedium)
            Spacer(modifier = Modifier.height(8.dp))
            LazyColumn {
              items(notes) { note ->
                Text(
                  text = note.text,
                  modifier = Modifier
                    .fillMaxWidth()
                    .clickable {
                      noteText = note.text
                      currentNoteId = note.id
                    }
                    .pointerInput(Unit) {
                      detectTapGestures(
                        onLongPress = {
                          scope.launch {
                            withContext(Dispatchers.IO) {
                              noteDao.delete(note)
                            }
                            if (currentNoteId == note.id) {
                              noteText = ""
                              currentNoteId = null
                            }
                            refreshNotes()
                          }
                        }
                      )
                    }
                    .padding(8.dp),
                  style = MaterialTheme.typography.bodyLarge
                )
                Divider()
              }
            }
          }
        }
      )
    }
  }
}

This solution uses Room to store notes with an auto-generated ID and text field.

The NoteDao interface defines suspend functions for insert, update, delete, and select all notes using Room annotations.

The Compose UI has an OutlinedTextField for entering note text, and two buttons: Save and Update.

Save inserts a new note if text is not blank. Update modifies the selected note by ID.

The notes are displayed in a scrollable list using LazyColumn. Clicking a note loads it into the text field for editing.

Long pressing a note deletes it from the database.

Coroutines run database operations off the main thread to keep UI smooth.

Final Result
Completed Screen
-------------------------
| Simple Notes          |
-------------------------
| [Enter note here_____]|
| [Save] [Update]       |
|-----------------------|
| Notes List:           |
| 1. Buy groceries      |
| 2. Call mom           |
| 3. Read book          |
-------------------------
User types text in the input field.
Tapping Save adds a new note to the list below.
Tapping a note loads its text into the input field for editing.
Tapping Update saves changes to the selected note.
Long pressing a note deletes it from the list.
Stretch Goal
Add a confirmation dialog before deleting a note on long press.
💡 Hint
Use Compose's AlertDialog composable to ask user to confirm deletion.