0% found this document useful (0 votes)
0 views

Exercise 8 - RoomDB_Course

The document outlines the steps to create an Android application using Kotlin for CRUD operations on a Course entity with a Room database. It details the setup of the Android project, creation of the Course entity and DAO, Room database configuration, RecyclerView setup, and implementation of CRUD operations in MainActivity. Additionally, it references a second lab for creating a Bus Schedule application using Room DB and Jetpack Compose.

Uploaded by

chiendv.23ite
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
0 views

Exercise 8 - RoomDB_Course

The document outlines the steps to create an Android application using Kotlin for CRUD operations on a Course entity with a Room database. It details the setup of the Android project, creation of the Course entity and DAO, Room database configuration, RecyclerView setup, and implementation of CRUD operations in MainActivity. Additionally, it references a second lab for creating a Bus Schedule application using Room DB and Jetpack Compose.

Uploaded by

chiendv.23ite
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 12

ROOM DATABASE

*Lab 1:
Creating a Android application for CRUD operations on a Course (Int id, String name,
and String description), using Room database.

Solution:
To create a Kotlin Android application that performs CRUD (Create, Read, Update, Delete)
operations on a Course entity using SQLiteOpenHelper, you'll follow these steps:
1. Set up your Android project and Add Room Dependencies
2. Create the Course Entity
3. Create the DAO (Data Access Object)

1
4. Set Up the Room Database
5. Adapter and RecyclerView Setup
6. Create CRUD Operations in MainActivity

Step 1: Set up your Android project


- File > New > New project > Empty Views Activity > Click Next
- Enter Project name, location, language (kotlin), min SDK, Groovy DSL > Click Finish
- Add Room Dependencies: build.gradle (module app)

apply plugin: 'kotlin-kapt'


dependencies {
// Room
implementation "androidx.room:room-runtime:2.6.1"
kapt "androidx.room:room-compiler:2.6.1" // Use kapt for
annotation processing
}

Step 2: Create the Course Entity


Right click on Package folder > New > Kotlin Class > Data Class: Course

2
import androidx.room.Entity
import androidx.room.PrimaryKey

@Entity(tableName = "course_table")
data class Course(
@PrimaryKey(autoGenerate = true) val id: Int = 0,
val name: String,
val description: String
)

Step 3: Create the DAO (Data Access Object)


Right click on Package folder > New > Kotlin Class > Interface: CourseDao

import androidx.room.*

@Dao
interface CourseDao {
@Insert
fun insertCourse(course: Course)

@Update
fun updateCourse(course: Course)

@Delete
fun deleteCourse(course: Course)

@Query("SELECT * FROM course_table")


fun getAllCourses(): List<Course>
}

Step 4: Set Up the Room Database


Right click on Package folder > New > Kotlin Class > Class: AppDatabase

import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase

3
import android.content.Context

@Database(entities = [Course::class], version = 1, exportSchema =


false)
abstract class AppDatabase : RoomDatabase() {

abstract fun courseDao(): CourseDao

companion object {
@Volatile
private var INSTANCE: AppDatabase? = null

fun getDatabase(context: Context): AppDatabase {


val tempInstance = INSTANCE
if (tempInstance != null) {
return tempInstance
}
synchronized(this) {
val instance = Room.databaseBuilder(
context.applicationContext,
AppDatabase::class.java,
"course_database"
).build()
INSTANCE = instance
return instance
}
}
}
}

Step 5: Create a layout for RecyclerView Item


Right click on res/layout > New > Layout resources file > Name: item_course

<?xml version="1.0" encoding="utf-8"?>


<androidx.cardview.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:padding="16dp">

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"

4
android:orientation="horizontal"
android:gravity="center_vertical">

<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical">

<TextView
android:id="@+id/textViewCourseName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="bold"
android:textSize="18sp"/>

<TextView
android:id="@+id/textViewCourseDescription"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="14sp"
android:layout_marginTop="4dp"
android:textColor="@android:color/darker_gray"/>
</LinearLayout>

<!-- Buttons Container -->


<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_gravity="end">

<Button
android:id="@+id/buttonUpdate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Update"
android:textColor="@android:color/white" />

<Button
android:id="@+id/buttonDelete"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Delete"
android:textColor="@android:color/white"
android:layout_marginStart="8dp" />
</LinearLayout>

5
</LinearLayout>

</androidx.cardview.widget.CardView>

Step 6: Create Adapter class for RecyclerView


Right click on Package folder > New > Kotlin Class > Class: CourseAdapter

import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView

class CourseAdapter(
var courses: MutableList<Course>, // Make 'courses' accessible
private val editClickListener: (Course) -> Unit,
private val deleteClickListener: (Course) -> Unit
) : RecyclerView.Adapter<CourseAdapter.CourseViewHolder>() {

inner class CourseViewHolder(itemView: View) :


RecyclerView.ViewHolder(itemView) {
private val courseName: TextView =
itemView.findViewById(R.id.textViewCourseName)
private val courseDescription: TextView =
itemView.findViewById(R.id.textViewCourseDescription)
private val buttonEdit: Button =
itemView.findViewById(R.id.buttonUpdate)
private val buttonDelete: Button =
itemView.findViewById(R.id.buttonDelete)

fun bind(course: Course, editClickListener: (Course) ->


Unit, deleteClickListener: (Course) -> Unit) {
courseName.text = course.name
courseDescription.text = course.description
buttonEdit.setOnClickListener {
editClickListener(course) }
buttonDelete.setOnClickListener {
deleteClickListener(course) }
}
}

init {
// Enable stable IDs
setHasStableIds(true)

6
}

override fun onCreateViewHolder(parent: ViewGroup, viewType:


Int): CourseViewHolder {
val view =
LayoutInflater.from(parent.context).inflate(R.layout.item_course,
parent, false)
return CourseViewHolder(view)
}

override fun onBindViewHolder(holder: CourseViewHolder,


position: Int) {
val course = courses[position]
holder.bind(course, editClickListener, deleteClickListener)
}

override fun getItemCount(): Int {


return courses.size
}

override fun getItemId(position: Int): Long {


// Return the unique ID of the course as the stable ID
return courses[position].id.toLong()
}

fun updateCourses(newCourses: List<Course>) {


courses.clear()
courses.addAll(newCourses)
notifyDataSetChanged()
}
}

Step7: MainActivity:
- Activity_Main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">

7
<EditText
android:id="@+id/editTextCourseName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Course Name"/>

<EditText
android:id="@+id/editTextCourseDescription"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Course Description"/>

<Button
android:id="@+id/buttonAddCourse"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Add Course"/>

<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerViewCourses"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"/>
</LinearLayout>
- MainActivity.kt
import android.os.Bundle
import android.widget.Button
import android.widget.EditText
import android.widget.Toast
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext

class MainActivity : AppCompatActivity() {

private lateinit var editTextCourseName: EditText


private lateinit var editTextCourseDescription: EditText
private lateinit var buttonAddCourse: Button

8
private lateinit var recyclerViewCourses: RecyclerView
private lateinit var courseAdapter: CourseAdapter
private lateinit var database: AppDatabase
private var selectedCourse: Course? = null
private var selectedPosition: Int = -1 // Keep track of
selected position for update

override fun onCreate(savedInstanceState: Bundle?) {


super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContentView(R.layout.activity_main)

ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)
) { v, insets ->
val systemBars =
insets.getInsets(WindowInsetsCompat.Type.systemBars())
v.setPadding(systemBars.left, systemBars.top,
systemBars.right, systemBars.bottom)
insets
}

// Initialize views
editTextCourseName =
findViewById(R.id.editTextCourseName)
editTextCourseDescription =
findViewById(R.id.editTextCourseDescription)
buttonAddCourse = findViewById(R.id.buttonAddCourse)
recyclerViewCourses =
findViewById(R.id.recyclerViewCourses)

// Initialize database
database = AppDatabase.getDatabase(this)

// Initialize RecyclerView
recyclerViewCourses.layoutManager =
LinearLayoutManager(this)
courseAdapter = CourseAdapter(mutableListOf(), { course -
> editCourse(course) }, { course -> deleteCourse(course) })
recyclerViewCourses.adapter = courseAdapter

// Load existing courses


loadCourses()

// Add or update course on button click


buttonAddCourse.setOnClickListener {
val name = editTextCourseName.text.toString().trim()
val description =

9
editTextCourseDescription.text.toString().trim()

if (name.isEmpty() || description.isEmpty()) {
Toast.makeText(this, "Please enter both name and
description", Toast.LENGTH_SHORT).show()
return@setOnClickListener
}

lifecycleScope.launch(Dispatchers.IO) {
if (selectedCourse == null) {
// Insert new course
val course = Course(name = name, description
= description)
database.courseDao().insertCourse(course)
} else {
// Update existing course
val updatedCourse = Course(id =
selectedCourse!!.id, name = name, description = description)

database.courseDao().updateCourse(updatedCourse)

// Notify adapter about the change at the


specific position
withContext(Dispatchers.Main) {
selectedCourse = null
buttonAddCourse.text = "Add Course"

courseAdapter.notifyItemChanged(selectedPosition)
}
}
loadCourses()
}
clearInputFields()
}
}

private fun loadCourses() {


lifecycleScope.launch(Dispatchers.IO) {
val courses = database.courseDao().getAllCourses()
withContext(Dispatchers.Main) {
courseAdapter.updateCourses(courses)
}
}
}

private fun clearInputFields() {


editTextCourseName.text.clear()

10
editTextCourseDescription.text.clear()
}

private fun editCourse(course: Course) {


selectedCourse = course
selectedPosition = courseAdapter.courses.indexOf(course)
// Save the current position
editTextCourseName.setText(course.name)
editTextCourseDescription.setText(course.description)
buttonAddCourse.text = "Update Course"
}

private fun deleteCourse(course: Course) {


lifecycleScope.launch(Dispatchers.IO) {
database.courseDao().deleteCourse(course)
loadCourses()
}
}
}

* Lab 2: Create a Bus Schedule application by Room DB and Jetpack


Compose

https://developer.android.com/codelabs/basic-android-kotlin-compose-
practice-bus-schedule-
app?hl=vi&continue=https%3A%2F%2F2.zoppoz.workers.dev%3A443%2Fhttps%2Fdeveloper.android.com%2Fcourse
11
s%2Fpathways%2Fandroid-basics-compose-unit-6-pathway-
2%3Fhl%3Dvi%23codelab-
https%3A%2F%2F2.zoppoz.workers.dev%3A443%2Fhttps%2Fdeveloper.android.com%2Fcodelabs%2Fbasic-android-
kotlin-compose-practice-bus-schedule-app#0

12

You might also like