Cannot access elements with a specific attribute from my dao (Android Room)

I am making a toDoList app with multiple users. I have two entities. One is User and the other one is Task

@Entity(tableName = "tasks")
data class Task(
@PrimaryKey(autoGenerate = true)
val id : Int,
val taskUserId : Int,
val taskName : String,
val taskDescription : String,
var taskPriority : Int)


@Entity(tableName = "users")
data class User(
@PrimaryKey
val userId : Int,
val userName : String,
val password : String)

As you can see the two entities need to have one thing in common and that would be the users id so I could query for tasks based on the users id. This is what my dao looks like:

@Dao
interface UserDao {

@Query("SELECT * FROM users")
fun getAllUsers() : LiveData<List<User>>

@Query("SELECT * FROM tasks WHERE taskUserId LIKE :userId ORDER BY taskPriority DESC")
fun getAllUsersTasks(userId : Int) : LiveData<List<Task>>

@Insert
suspend fun saveUser(user : User)

@Insert
suspend fun saveTask(task : Task)
}

And here are the other model elements:

class TaskRepository(private val userDao: UserDao) {

var userId : Int = 0
val allTasks = userDao.getAllUsersTasks(userId)
val allUsers : LiveData<List<User>> = userDao.getAllUsers()

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

suspend fun saveTask(task : Task){
    userDao.saveTask(task)
    }
}

And the ViewModel:

class MainViewModel(application: Application) : AndroidViewModel(application) {

private val taskRepository : TaskRepository

val allTasks : LiveData<List<Task>>
val allUsers : LiveData<List<User>>
private var userId  : Int = 0


init {
    val taskDao = UserTasksDatabase.getDatabase(application)!!.userDao()
    taskRepository = TaskRepository(taskDao)
    allTasks = taskRepository.allTasks
    allUsers = taskRepository.allUsers
    taskRepository.userId = this.userId
}


fun saveUser(user: User) = viewModelScope.launch(Dispatchers.IO){
    taskRepository.saveUser(user)
}

fun saveTask(task: Task) = viewModelScope.launch(Dispatchers.IO){
    taskRepository.saveTask(task)
}

fun setUserId(id : Int){
    this.userId = id
}

fun getUserId() : Int{
    return this.userId
    }

}

When the user pushes the login or the sign up button I set the user's id in the viewModel

 logInButton.setOnClickListener {
        val userName: String = userNameEditText.text.toString()
        val password: String = passwordEditText.text.toString()
        val id: Int = IdMaker.generateId(userName)
        val user = User(id, userName, password)

        if(listOfAllUsers.contains(user)){
            sharedViewModel.setUserId(id)
            Toast.makeText(requireContext(), "Welcome $userName", Toast.LENGTH_LONG).show()
            fragmentManager!!.beginTransaction().apply {
                replace(R.id.fl_activity_main, MainFragment())
                commit()
            }
        }else{
            Toast.makeText(requireContext(), "The user already exists", Toast.LENGTH_LONG).show()
        }
    }

But when i try to access the users in the main fragment and set them on my recyclerview I get nothing. And I can't really see what am I missing.

sharedViewModel.allTasks.observe(this, Observer {tasks ->
        tasks.let { adapter.setTasks(it) }
    })

I'm sorry if a question is a bit simple but I hope I will gain some insight in what am I missing.

Side note: The recyclerview is set up properly and tested.

Upvotes: 0

Views: 122

Answers (1)

Dat Pham Tat
Dat Pham Tat

Reputation: 1463

I think you are not setting the TaskRepository.userId correctly.

class MainViewModel(application: Application) : AndroidViewModel(application) {
    private val taskRepository : TaskRepository
    private var userId  : Int = 0

    init {
        ...
        // init is called only once at the start of this viewModel's instance creation
        // Here, you set your repository's userId to 0
        taskRepository.userId = this.userId
    }
}

At the instance creation of your MainViewModel, you set the userId of its TaskRepository instance to 0, which in your following codes is not changed anymore. Upon your login button click, you do call:

sharedViewModel.setUserId(id)

but the function alters only the viewModel's userId property, not the userId property of your TaskRepository instance. So try:

class MainViewModel(application: Application) : AndroidViewModel(application) {
    private lateinit var taskRepository : TaskRepository
    val allTasks = taskRepository.allTasks
    val allUsers = taskRepository.allUsers


    // remove init {}
    
    fun setUserId(id : Int){
        // set up the repository only after userId is known
        val taskDao = UserTasksDatabase.getDatabase(application)!!.userDao()
        taskRepository = TaskRepository(taskDao, id)
    }
}

And alter your TaskRepository class:

class TaskRepository(private val userDao: UserDao, private val userId: Int) {
    val allTasks: LiveData<List<Task>> 
        get() = userDao.getAllUsersTasks(userId)
    val allUsers: LiveData<List<User>>
        get() = userDao.getAllUsers()

    ...
}

Upvotes: 0

Related Questions