Search code examples
androidkotlinfilterandroid-roomandroid-livedata

How to implement a Room LiveData filter


I do not know how to implement a filter query properly inside the Repository and the ViewModel to use it to display the filtered string in a Textview or anything else really. My Entity, Dao, Repository, and ViewModel are as follows:

User.kt

@Entity(tableName = "user_data")
data class User (
    @PrimaryKey(autoGenerate = true) val id: Int,
    @ColumnInfo(name = "name") val name: String
)

UserDao.kt

@Dao
interface UserDao {
    @Insert
    fun addUser(user: User)

    @Query("SELECT name FROM user_data WHERE name LIKE :filter LIMIT 1")
    fun getFilteredUser(filter: String): LiveData<String>
}

UserRepository.kt

class UserRepository(private val userDao: UserDao) {

     fun addUser(user: User) { userDao.addUser(User) }

     fun getFilteredUser(filter: String) {userDao.getFilteredUser(filter)}
}

UserViewModel.kt

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

    private val repository: UserRepository

    init {
        val userDao = UserDatabase.getDatabase(application).userDao()
        repository = UserRepository(userDao )    
    }

    fun addUser(user: User) {
        viewModelScope.launch(Dispatchers.IO){
            repository.addUser(user)
        }
    }

    fun getFilteredUser(filter: String){
        return repository.getFilteredUser(filter)
    }
}

How would I proceed from here to make it possible to e.g. display the filtered User String in a textview or anything like that and how do I write the method correctly inside the repository and the viewmodel? Thank you for your help!


Solution

  • Try the following

    UserDao

    change getFilteredUser as follows

        @Query("SELECT name FROM user_data WHERE name LIKE '%' || :filter || '%' LIMIT 1")
        fun getFilteredUser(filter: String): Stringl̥
    

    UserRepo

    use coroutines to perform the database I/O operations

        suspend fun addUser(user: User) {
            withContext(Dispatchers.IO) {
                userDao.addUser(user)
            }
        }
    
        suspend fun getFilteredUser(filter: String): String {
            return withContext(Dispatchers.IO) {
                userDao.getFilteredUser(filter)
            }
        }
    

    ViewModel

        fun addUser(user: User) {
            viewModelScope.launch {
                repository.addUser(user)
            }
        }
    
        private val _dataToUi = MutableLiveData<String>()
        val dataToUi: LiveData<String>
            get() = _dataToUi
    
        suspend fun getFilteredUser(filter: String): String? {
            return withContext(Dispatchers.IO) {
                repository.getFilteredUser(filter)
            }
        }
    
        // to set the filterquery from the fragment/activity
        fun setFliterQuery(query: String) {
            viewModelScope.launch {
                _dataToUi.value = getFilteredUser(query)
            }
        }
    

    Activity

            binding.button.setOnClickListener {
                val queryKey = binding.queryKey.text.toString()
                Log.i("activity", queryKey)
                userViewModel.setFliterQuery(queryKey)
            }
    
            userViewModel.dataToUi.observe(this) { result ->
                result?.apply {
                    Log.i("activity", result)
                    binding.resultText.text = result
                }
            }