Mon. Sep 16th, 2024

build.gradle

plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.jetbrains.kotlin.android)
id("kotlin-kapt")
}

android {
namespace = "com.androindian.roomdatabase"
compileSdk = 34

defaultConfig {
applicationId = "com.androindian.roomdatabase"
minSdk = 24
targetSdk = 34
versionCode = 1
versionName = "1.0"

testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}

buildTypes {
release {
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = "1.8"
}
dataBinding{
enable=true
}
}

dependencies {

implementation(libs.androidx.core.ktx)
implementation(libs.androidx.appcompat)
implementation(libs.material)
implementation(libs.androidx.activity)
implementation(libs.androidx.constraintlayout)
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core)
implementation("androidx.room:room-runtime:2.6.1")
kapt("androidx.room:room-compiler:2.6.1")
implementation("androidx.room:room-ktx:2.6.1")

// ViewModel and LiveData
implementation ("androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.1")
implementation ("androidx.lifecycle:lifecycle-runtime-ktx:2.6.1")

// Coroutines
implementation ("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.1")
}

activity_main.xml

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

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="16dp">

<EditText
android:id="@+id/etUsername"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Username"
android:inputType="textPersonName" />

<EditText
android:id="@+id/etEmail"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Email"
android:inputType="textEmailAddress" />

<EditText
android:id="@+id/etMobile"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Mobile"
android:inputType="phone" />

<EditText
android:id="@+id/etPassword"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Password"
android:inputType="textPassword" />

<Button
android:id="@+id/btnSave"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Save User" />

<Button
android:id="@+id/btnLoad"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Load Users" />

<Button
android:id="@+id/btnDelete"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Delete All Users" />

</LinearLayout>

MainActivity.kt

This activity interacts with the database through the UserViewModel

package com.androindian.roomdb


import android.os.Bundle
import android.widget.Button
import android.widget.EditText
import android.widget.Toast
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import androidx.room.Room
import kotlinx.coroutines.launch

class MainActivity : AppCompatActivity() {

private lateinit var userViewModel: UserViewModel

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)

val database = Room.databaseBuilder(
applicationContext,
UserDatabase::class.java,
"user_database"
).build()

val repository = UserRepository(database.userDao())
val viewModelFactory = UserViewModelFactory(repository)
userViewModel = ViewModelProvider(this, viewModelFactory).get(UserViewModel::class.java)

val etUsername = findViewById<EditText>(R.id.etUsername)
val etEmail = findViewById<EditText>(R.id.etEmail)
val etMobile = findViewById<EditText>(R.id.etMobile)
val etPassword = findViewById<EditText>(R.id.etPassword)
val btnSave = findViewById<Button>(R.id.btnSave)
val btnLoad = findViewById<Button>(R.id.btnLoad)
val btnDelete = findViewById<Button>(R.id.btnDelete)

btnSave.setOnClickListener {
val user = User(
username = etUsername.text.toString(),
email = etEmail.text.toString(),
mobile = etMobile.text.toString(),
password = etPassword.text.toString()
)
lifecycleScope.launch {
userViewModel.insert(user)
Toast.makeText(this@MainActivity, "User Saved", Toast.LENGTH_SHORT).show()
}
}

btnLoad.setOnClickListener {
lifecycleScope.launch {
val users = userViewModel.getAllUsers()
users.forEach { user ->
Toast.makeText(this@MainActivity, "User: ${user.username}, Email: ${user.email}", Toast.LENGTH_SHORT).show()
}
}
}

btnDelete.setOnClickListener {
lifecycleScope.launch {
userViewModel.deleteAll()
Toast.makeText(this@MainActivity, "All Users Deleted", Toast.LENGTH_SHORT).show()
}
}
}
}

User.kt

This class represents the user entity in the database.

package com.androindian.roomdb

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

@Entity(tableName = "user_table")
data class User(
@PrimaryKey(autoGenerate = true) val id: Int = 0,
val username: String,
val email: String,
val mobile: String,
val password: String
)

UserDao.kt

This interface defines the methods for accessing the database.

package com.androindian.roomdb

import androidx.room.*

@Dao
interface UserDao {

@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insert(user: User)

@Update
suspend fun update(user: User)

@Delete
suspend fun delete(user: User)

@Query("SELECT * FROM user_table ORDER BY username ASC")
suspend fun getAllUsers(): List<User>

@Query("DELETE FROM user_table")
suspend fun deleteAll()
}
UserDatabase.kt
This class provides the database instance.
package com.androindian.roomdb

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

@Database(entities = [User::class], version = 1, exportSchema = false)
abstract class UserDatabase : RoomDatabase() {
abstract fun userDao(): UserDao
}
UserRepository.kt
This class handles data operations, interacting with the DAO.
package com.androindian.roomdb

class UserRepository(private val userDao: UserDao) {

suspend fun insert(user: User) {
userDao.insert(user)
}

suspend fun update(user: User) {
userDao.update(user)
}

suspend fun delete(user: User) {
userDao.delete(user)
}

suspend fun getAllUsers(): List<User> {
return userDao.getAllUsers()
}

suspend fun deleteAll() {
userDao.deleteAll()
}
}
UserViewModel.kt

This class interacts with the repository and provides data to the UI.
package com.androindian.roomdb
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.launch


class UserViewModel(private val repository: UserRepository) : ViewModel() {


fun insert(user: User) = viewModelScope.launch {
repository.insert(user)
}

fun update(user: User) = viewModelScope.launch {
repository.update(user)
}

fun delete(user: User) = viewModelScope.launch {
repository.delete(user)
}

suspend fun getAllUsers(): List<User> {
return repository.getAllUsers()
}

fun deleteAll() = viewModelScope.launch {
repository.deleteAll()
}
}

class UserViewModelFactory(private val repository: UserRepository) : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
if (modelClass.isAssignableFrom(UserViewModel::class.java)) {
@Suppress("UNCHECKED_CAST")
return UserViewModel(repository) as T
}
throw IllegalArgumentException("Unknown ViewModel class")
}
}

By Rajashekar

I’m (Rajashekar) a core Android developer with complimenting skills as a web developer from India. I cherish taking up complex problems and turning them into beautiful interfaces. My love for decrypting the logic and structure of coding keeps me pushing towards writing elegant and proficient code, whether it is Android, PHP, Flutter or any other platforms. You would find me involved in cuisines, reading, travelling during my leisure hours.

Leave a Reply

Your email address will not be published. Required fields are marked *