`The Task data is not being inserted in database, therefore not collected and rendered in UI.
#TaskViewModel.kt
var taskList: StateFlow<List<Task>> = repository.getAllTasks()
.stateIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(5000),
initialValue = emptyList()
)
#HomeScreen.kt
val tasks by taskViewModel.taskList.collectAsState()
I was expecting test data to be displayed in UI when the app is run.
#HomeScreen.kt
@Composable
fun HomeScreen(taskViewModel: TaskViewModel, modifier: Modifier = Modifier) {
val tasks by taskViewModel.taskList.collectAsState()
Column(
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center,
modifier = modifier.fillMaxSize()
) {
IconButton(
modifier = Modifier.size(100.dp),
onClick = {
//todo : remove after testing
(1..10).map { index ->
taskViewModel.insertTask(
Task(
id = index,
title = "Task $index",
isCompleted = index % 2 == 0,
startTime = System.currentTimeMillis(),
endTime = System.currentTimeMillis() + (index * 2) * 3600000
)
)
}
},
) {
Icon(
imageVector = Icons.Default.Add,
contentDescription = null,
modifier = Modifier.size(100.dp)
)
}
//Spacer(modifier = Modifier.height(10.dp))
Card(
shape = RoundedCornerShape(8.dp), colors = CardDefaults.cardColors(Color.LightGray)
) {
Text(
text = "Tasks:", fontSize = 20.sp
)
Spacer(modifier = Modifier.height(10.dp))
LazyColumn(
modifier = Modifier
.fillMaxSize()
.padding(16.dp, 0.dp)
) {
items(items = tasks, key = { it.id }) {
TaskComponent(task = it)
Spacer(modifier = Modifier.height(10.dp))
}
}
}
}
}
#TaskComponent.kt
@Composable
fun TaskComponent(task: Task, modifier: Modifier = Modifier) {
Box(
modifier = Modifier
.fillMaxWidth()
.background(color = Color.White, shape = RoundedCornerShape(8.dp))
.padding(start = 10.dp)
.size(50.dp)
) {
Text(text = task.title, fontSize = 20.sp)
}
}
#TaskViewModel.kt
@HiltViewModel
class TaskViewModel @Inject constructor(private val repository: TaskRepository) : ViewModel() {
var task: Task by mutableStateOf(
Task(0, "", false, 0, 0)
)
private set
var taskList: StateFlow<List<Task>> = repository.getAllTasks()
.stateIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(5000),
initialValue = emptyList()
)
fun insertTask(task: Task) {
viewModelScope.launch {
repository.insert(task)
}
}
fun updateTask(task: Task) {
viewModelScope.launch {
repository.update(task)
}
}
fun deleteTask(task: Task) {
viewModelScope.launch {
repository.delete(task)
}
}
fun getTaskById(id: Int) {
viewModelScope.launch {
repository.getTaskById(id)
}
}
fun getAllTasks() {
viewModelScope.launch {
repository.getAllTasks()
}
}
}
#Task.kt
@Entity(tableName = "tasks_tbl")
data class Task(
@PrimaryKey(autoGenerate = true) val id: Int=0,
val title: String,
val isCompleted: Boolean,
val startTime: Long,
val endTime: Long
)
#TaskDao.kt
package com.example.crudapp.data
import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.Query
import androidx.room.Update
import kotlinx.coroutines.flow.Flow
@Dao
interface TaskDao {
@Insert
suspend fun insertTask(task: Task) {
}
@Update
suspend fun updateTask(task: Task) {
}
@Delete
suspend fun deleteTask(task: Task) {
}
@Query("SELECT * FROM tasks_tbl WHERE id=:id")
fun getTaskById(id: Int): Flow<Task>
@Query("SELECT * FROM tasks_tbl")
fun getAllTasks(): Flow<List<Task>>
}
#TaskDatabase.kt
@Database(entities = [Task::class], version = 1, exportSchema = false)
abstract class TaskDatabase : RoomDatabase() {
abstract fun taskDao(): TaskDao
}
#TaskRepository.kt
class TaskRepository(private val dao: TaskDao) {
suspend fun insert(task: Task) {
dao.insertTask(task)
}
suspend fun update(task: Task) {
dao.updateTask(task)
}
suspend fun delete(task: Task) {
dao.deleteTask(task)
}
fun getTaskById(id: Int): Flow<Task> {
return dao.getTaskById(id)
}
fun getAllTasks(): Flow<List<Task>> {
return dao.getAllTasks()
}
}
#AppModule.kt
@Module
@InstallIn(SingletonComponent::class)
object AppModule {
@Provides
@Singleton
fun providesLocalDatabase(@ApplicationContext context: Context): TaskDatabase {
return Room.databaseBuilder(context, TaskDatabase::class.java, "task_db")
.build()
}
@Provides
@Singleton
fun providesTaskDao(db: TaskDatabase): TaskDao {
return db.taskDao()
}
@Provides
@Singleton
fun providesTaskRepository(dao: TaskDao): TaskRepository {
return TaskRepository(dao)
}
}
Remove the { }
from after the function definitions in the DAO. The brackets are defining an empty (do-nothing) default implementation of the functions, but you want to allow Room to define its own implementation for these functions.
I’m not sure if it’s intended for Room to misbehave when you have default function implementations, but maybe it is designed this way so you can define temporary test functions that behave differently.