In this Jetpack compose tutorial we will learn how to use Room database with Jetpack compose in Android application.
Room is one of android architecture component, which is an abstract layer for the SqLite Database
By using the room we can handle the SQLite Database is easily
Room provides the following benefits
Read more about Room Database with Kotlin
Let's get started
Step 1: Create android application in android studio
Step 2: Follow step for setup Jetpack Compose with Android Studio
plugins { id 'com.android.application' id 'kotlin-android' id 'kotlin-kapt' } kapt { correctErrorTypes = true } dependencies { def room_version = "2.3.0" implementation "androidx.room:room-ktx:$room_version" kapt "androidx.room:room-compiler:$room_version" } |
Primary components
There are three major components in Room:
Data entity
The following code defines a Customer data entity. Each instance of Customer represents a row in a customer table in the app's database
@Entity(tableName = "customer") data class Customer( @PrimaryKey(autoGenerate = true) val id: Int = 0, @ColumnInfo(name = "name") val name: String?, @ColumnInfo(name = "gender") val gender: String?, @ColumnInfo(name = "email_id") val emailId: String? ) |
Data access object (DAO)
The following code defines a DAO called CustomerDao. CustomerDao provides the methods that the rest of the app uses to interact with data in the customer table
@Dao interface CustomerDao { @Query("SELECT * FROM customer") fun fetchAllCustomer(): LiveData> @Insert(onConflict = OnConflictStrategy.REPLACE) suspend fun insertCustomer(customer: Customer) @Query("DELETE FROM Customer where id = :id") suspend fun deleteCustomerById(id: Int) @Query("DELETE FROM customer") suspend fun deleteAllCustomer() } |
Database
The following code defines an AppDatabase class, Database class which is abstract class annotated by @Database. @Database annoation having the fileds
entities -> represents the tables which we are going to use in the Database.
version -> represetns databse version
exportSchema -> represents, do we need to export our database schema into specified folder location, by default its value is true
@Database(entities = [Customer::class], version = 1, exportSchema = false) abstract class AppDatabase : RoomDatabase() { abstract fun customerDao(): CustomerDao 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, "jetpack") .build() INSTANCE = instance return instance } } } } |
Repository
In this Compose Room Database example we are going to manage the Data by using the repository patterns
class CustomerRepository(application: Application) { private var customerDao: CustomerDao init { val database = AppDatabase.getDatabase(application) customerDao = database.customerDao() } val readAllCustomer: LiveData> = customerDao.fetchAllCustomer() suspend fun insertUser(customer: Customer) { customerDao.insertCustomer(customer) } suspend fun deleteCustomerById(id: Int) { customerDao.deleteCustomerById(id) } suspend fun deleteAllCustomer() { customerDao.deleteAllCustomer() } init { val database = AppDatabase.getDatabase(application) customerDao = database.customerDao() } } |
Viewmodel
class CustomerViewmodel(appObj: Application) : AndroidViewModel(appObj) {
private val customerRepository: CustomerRepository = CustomerRepository(appObj)
fun fetchAllCustomer(): LiveData> {
return customerRepository.readAllCustomer
}
fun insertCustomer(customer: Customer) {
viewModelScope.launch {
customerRepository.insertUser(customer = customer)
}
}
fun deleteCustomerById(id: Int) {
viewModelScope.launch {
customerRepository.deleteCustomerById(id)
}
}
}
|
Here is the activity code where we will create ViewModel instance and handle the Database results and display it on listview
class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE) val customerViewModel = ViewModelProvider(this).get(CustomerViewmodel::class.java) setContent { MaterialTheme { // A surface container using the 'background' color from the theme Surface(color = MaterialTheme.colors.background) { CustomerList(customerViewModel) } } } } } @Composable fun CustomerList(customerViewModel: CustomerViewmodel) { val customerList = customerViewModel.fetchAllCustomer().observeAsState(arrayListOf()) Scaffold(modifier = Modifier.fillMaxSize(), floatingActionButton = { ExtendedFloatingActionButton( backgroundColor = Color.Red, text = { Text(text = "Customer", color = Color.White) }, onClick = { val name = UUID.randomUUID().toString() customerViewModel.insertCustomer( Customer( name = name, gender = "Male", emailId = "xyz@gmail.com" ), ) }, icon = { Icon( imageVector = Icons.Default.Add, contentDescription = "image", tint = Color.White ) }) }, content = { LazyColumn(content = { items( items = customerList.value, itemContent = { Row( modifier = Modifier .fillMaxWidth() .padding(horizontal = 16.dp, vertical = 8.dp), content = { val color = Color( Random.nextInt(256), Random.nextInt(256), Random.nextInt(256) ) Box( content = { Text( text = (it.name ?: "")[0].uppercase(), fontSize = 24.sp, color = color ) }, modifier = Modifier .size(80.dp) .border(width = 1.2.dp, color = color, shape = CircleShape), contentAlignment = Alignment.Center ) Spacer(modifier = Modifier.size(16.dp)) Column( modifier = Modifier.weight(2F), content = { Spacer(modifier = Modifier.size(8.dp)) Text( text = it.name?.uppercase() ?: "", color = color, fontSize = 16.sp, maxLines = 1, overflow = TextOverflow.Ellipsis ) Text( text = "${it.gender}", color = Color.Black, fontSize = 14.6.sp ) Text( text = "${it.emailId}", color = Color.Gray, maxLines = 1, overflow = TextOverflow.Ellipsis ) }) Spacer(modifier = Modifier.size(16.dp)) Icon( imageVector = Icons.Default.Delete, contentDescription = "image", tint = Color.Red, modifier = Modifier .size(30.dp) .clickable(onClick = { customerViewModel.deleteCustomerById(it.id) }) ) }) }) }) }) } |
Complete Compose Room Database with MVVM code here
package com.example.jetpack import android.app.Application import android.content.Context import android.os.Bundle import android.view.WindowManager import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.compose.foundation.border 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.foundation.shape.CircleShape import androidx.compose.material.* import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Add import androidx.compose.material.icons.filled.Delete import androidx.compose.runtime.Composable import androidx.compose.runtime.livedata.observeAsState import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.LiveData import com.example.jetpack.ui.theme.JetPackTheme import com.example.jetpack.viewmodels.CustomerViewmodel import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.viewModelScope import androidx.room.* import com.example.jetpack.dao.CustomerDao import com.example.jetpack.datamodels.AppDatabase import com.example.jetpack.datamodels.Customer import com.example.jetpack.repository.CustomerRepository import com.example.jetpack.widget.CustomerList import kotlinx.coroutines.launch import java.util.* import kotlin.random.Random class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE) val customerViewModel = ViewModelProvider(this).get(CustomerViewmodel::class.java) setContent { MaterialTheme { // A surface container using the 'background' color from the theme Surface(color = MaterialTheme.colors.background) { CustomerList(customerViewModel) } } } } } @Composable fun CustomerList(customerViewModel: CustomerViewmodel) { val customerList = customerViewModel.fetchAllCustomer().observeAsState(arrayListOf()) Scaffold(modifier = Modifier.fillMaxSize(), floatingActionButton = { ExtendedFloatingActionButton( backgroundColor = Color.Red, text = { Text(text = "Customer", color = Color.White) }, onClick = { val name = UUID.randomUUID().toString() customerViewModel.insertCustomer( Customer( name = name, gender = "Male", emailId = "xyz@gmail.com" ), ) }, icon = { Icon( imageVector = Icons.Default.Add, contentDescription = "image", tint = Color.White ) }) }, content = { LazyColumn(content = { items( items = customerList.value, itemContent = { Row( modifier = Modifier .fillMaxWidth() .padding(horizontal = 16.dp, vertical = 8.dp), content = { val color = Color( Random.nextInt(256), Random.nextInt(256), Random.nextInt(256) ) Box( content = { Text( text = it.name[0].uppercase(), fontSize = 24.sp, color = color ) }, modifier = Modifier .size(80.dp) .border(width = 1.2.dp, color = color, shape = CircleShape), contentAlignment = Alignment.Center ) Spacer(modifier = Modifier.size(16.dp)) Column( modifier = Modifier.weight(2F), content = { Spacer(modifier = Modifier.size(8.dp)) Text( text = it.name.uppercase(), color = color, fontSize = 16.sp, maxLines = 1, overflow = TextOverflow.Ellipsis ) Text( text = "${it.gender}", color = Color.Black, fontSize = 14.6.sp ) Text( text = "${it.emailId}", color = Color.Gray, maxLines = 1, overflow = TextOverflow.Ellipsis ) }) Spacer(modifier = Modifier.size(16.dp)) Icon( imageVector = Icons.Default.Delete, contentDescription = "image", tint = Color.Red, modifier = Modifier .size(30.dp) .clickable(onClick = { customerViewModel.deleteCustomerById(it.id) }) ) }) }) }) }) } @Database(entities = [Customer::class], version = 1, exportSchema = false) abstract class AppDatabase : RoomDatabase() { abstract fun customerDao(): CustomerDao 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, "jetpack" ) .build() INSTANCE = instance return instance } } } } @Entity(tableName = "customer") data class Customer( @PrimaryKey(autoGenerate = true) val id: Int = 0, @ColumnInfo(name = "name") val name: String="", @ColumnInfo(name = "gender") val gender: String?, @ColumnInfo(name = "email_id") val emailId: String? ) @Dao interface CustomerDao { @Query("SELECT * FROM customer") fun fetchAllCustomer(): LiveData> @Insert(onConflict = OnConflictStrategy.REPLACE) suspend fun insertCustomer(customer: Customer) @Query("DELETE FROM Customer where id = :id") suspend fun deleteCustomerById(id: Int) } class CustomerRepository(application: Application) { private var customerDao: CustomerDao init { val database = AppDatabase.getDatabase(application) customerDao = database.customerDao() } val readAllCustomer: LiveData> = customerDao.fetchAllCustomer() suspend fun insertUser(customer: Customer) { customerDao.insertCustomer(customer) } suspend fun deleteCustomerById(id: Int) { customerDao.deleteCustomerById(id) } init { val database = AppDatabase.getDatabase(application) customerDao = database.customerDao() } } class CustomerViewmodel(appObj: Application) : AndroidViewModel(appObj) { private val customerRepository: CustomerRepository = CustomerRepository(appObj) fun fetchAllCustomer(): LiveData> { return customerRepository.readAllCustomer } fun insertCustomer(customer: Customer) { viewModelScope.launch { customerRepository.insertUser(customer = customer) } } fun deleteCustomerById(id: Int) { viewModelScope.launch { customerRepository.deleteCustomerById(id) } } } |
Conclusion: In this jetpack Compose tutorial we covered how to use Room Database with MVVM repository pattern.
Article Contributed By :
|
|
|
|
9112 Views |