Friday, October 15, 2021

jetpack compose - Room add remove update

MainActivity.kt

package com.example.composeroomexample

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Delete
import androidx.compose.material.icons.filled.Edit
import androidx.compose.runtime.Composable
import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel
import java.util.*
import kotlin.random.Random

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent { MainContent() }
    }
}


@Composable
fun MainContent(){
    val scope = rememberCoroutineScope()
    val model = viewModel<StudentViewModel>()
    val list:List<Student> = model.students.observeAsState(listOf()).value

    Column(
        modifier = Modifier.padding(12.dp),
        verticalArrangement = Arrangement.spacedBy(12.dp)
    ) {
        Row(
            horizontalArrangement = Arrangement.spacedBy(12.dp)
        ){
            // add new student
            Button(onClick = {
                model.insert(
                    Student(
                        null,UUID.randomUUID().toString(),
                        Random.nextInt(10,90)
                    )
                )
            }) { Text(text = "Add Student") }

            // delete all students
            Button(onClick = { model.clear() }) {
                Text(text = "Clear")
            }
        }

        LazyColumn(
            verticalArrangement = Arrangement.spacedBy(8.dp),
            contentPadding = PaddingValues(vertical = 12.dp)
        ) {
            itemsIndexed(list) { index,item ->
                Card(
                    modifier = Modifier.fillMaxWidth(),
                    backgroundColor = Color(0xFFA1CAF1)
                ) {
                    Row(
                        modifier = Modifier.padding(12.dp),
                        verticalAlignment = Alignment.CenterVertically
                    ) {

                        Box(
                            Modifier.size(48.dp).clip(CircleShape)
                                .background(Color(0xFFF0FFFF)),
                            contentAlignment = Alignment.Center
                        ) {
                            Text(
                                text = "${item.id}",
                                style = MaterialTheme.typography.h6
                            )
                        }

                        Spacer(modifier = Modifier.width(12.dp))
                        Text(
                            text = item.fullName.take(10),
                            style = MaterialTheme.typography.caption
                        )

                        Spacer(modifier = Modifier.width(12.dp))
                        Text(
                            text = " ${item.result}",
                            style = MaterialTheme.typography.h5
                        )
                        Spacer(modifier = Modifier.weight(1F))

                        // edit button
                        IconButton(onClick = {
                            val updatedItem = Student(
                                item.id,item.fullName,Random.nextInt(0,100)
                            )
                            model.update(updatedItem)
                        }) { Icon(Icons.Filled.Edit,"")}

                        // delete button
                        IconButton(onClick = { model.delete(item)}) {
                            Icon(Icons.Filled.Delete,"")
                        }
                    }
                }
            }
        }
    }
}
RoomSingleton.kt

package com.example.composeroomexample

import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
import android.content.Context

@Database(entities = [Student::class], version = 1, exportSchema = false)
abstract class RoomSingleton : RoomDatabase() {
    abstract fun studentDao():StudentDao

    companion object {
        private var INSTANCE: RoomSingleton? = null
        fun getInstance(context: Context): RoomSingleton {
            if (INSTANCE == null) {
                INSTANCE = Room.databaseBuilder(
                    context,
                    RoomSingleton::class.java,
                    "roomdb")
                    .build()
            }
            return INSTANCE as RoomSingleton
        }
    }
}
RoomEntity.kt

package com.example.composeroomexample

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

@Entity(tableName = "studentTbl")
data class Student(
    @PrimaryKey
    var id:Long?,

    @ColumnInfo(name = "uuid")
    var fullName: String,

    @ColumnInfo(name = "result")
    var result:Int
)
RoomDao.kt

package com.example.composeroomexample

import androidx.lifecycle.LiveData
import androidx.room.*

@Dao
interface StudentDao{
    @Query("SELECT * FROM studentTbl ORDER BY id DESC")
    fun getStudents():LiveData<MutableList<Student>>

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insert(student:Student)

    @Update
    suspend fun update(student:Student)

    @Delete
    suspend fun delete(student:Student)

    @Query("DELETE FROM studentTbl")
    suspend fun clear()
}
StudentViewModel.kt

package com.example.composeroomexample

import android.app.Application
import androidx.lifecycle.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch


class StudentViewModel(application:Application)
    : AndroidViewModel(application){
    
	private val db:RoomSingleton = RoomSingleton
        .getInstance(application)

    internal val students : LiveData<MutableList<Student>> =
        db.studentDao().getStudents()

    fun insert(student: Student){
        viewModelScope.launch(Dispatchers.IO) {
            db.studentDao().insert(student)
        }
    }

    fun update(student: Student){
        viewModelScope.launch(Dispatchers.IO) {
            db.studentDao().update(student)
        }
    }

    fun delete(student: Student){
        viewModelScope.launch(Dispatchers.IO) {
            db.studentDao().delete(student)
        }
    }

    fun clear(){
        viewModelScope.launch(Dispatchers.IO) {
            db.studentDao().clear()
        }
    }
}
build.gradle [dependencies]

apply plugin: 'kotlin-kapt'

dependencies {
    def room_version = "2.4.2"
    implementation "androidx.room:room-runtime:$room_version"
    implementation "androidx.room:room-ktx:$room_version"
    kapt "androidx.room:room-compiler:$room_version"

    implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.0-alpha06"
    implementation 'androidx.lifecycle:lifecycle-viewmodel-compose:2.5.0-alpha06'
    implementation 'androidx.compose.runtime:runtime-livedata:1.2.0-alpha07'
}