BENN1TH
BENN1TH

Reputation: 2023

Pass multiple Filters to Android Room Dao SQL Query from ViewModel with Repository

I am using the below to fetch Database rows to my Adapter, however I want to return rows from multi-filtered single query using either "LIKE" and/or "WHERE" and basically all sql query filter types, I can do one filter via MutableLiveData<String>();

end result would be like ...

@Query("SELECT * FROM mytable WHERE suburb LIKE '%' || :suburb || '%' postcode LIKE '%' || :postcode || '%' BETWEEN firstDate AND lastDate")
fun getFilteredRows(
    suburb: String?, 
    postcode: String?, 
    firstDate: String?, 
    lastDate: String?): LiveData<List<MyTable>>

As per below, currently way only can pass one filter var.

ViewModel Class

 class MyViewModel internal constructor(repository: MyRepository) : ViewModel()

 //filter by suburb
 var suburb = MutableLiveData<String>().apply { 
    //do I set as HashMap??
    value = SUBURB 
 }

 //LiveData Observer access
 val filteredRows: LiveData<List<MyTable>> = suburb.switchMap {

    //pass multiple filters to repository here
    //but currently only can pass one string to repository
    repository.getFilteredRows(it)

 }

 //MyViewModel function to set the suburb value
 fun setSuburb(_suburb: String) {
    suburb.value = _suburb
 }

 //companion object
 companion object {
    var SUBURB: String? = null
 }

Repository Class

class Repository private constructor(private val dao: Dao)

//basic repo to dao communtication
fun getFilteredRows(suburb: String?) = dao.getFilteredRows(suburb)

Dao Interface

@Dao
interface Dao

//here I want to receive multiple Strings to do filtering within the query
@Query("SELECT * FROM mytable WHERE suburb LIKE '%' || :suburb || '%'")
fun getFilteredRows(suburb: String?): LiveData<List<MyTable>>

I have tried with passing basic var Strings with no luck, seems only MutableLiveData is the way to pass variable to the Dao via ViewModel & Repository

Upvotes: 1

Views: 3057

Answers (1)

BENN1TH
BENN1TH

Reputation: 2023

** See Edit Below **

Not ideal to say the least, actually would not recommend, however, current work around is to "loop" through multiple MutableLiveData variables

ViewModel Class

var suburb = MutableLiveData<String>().apply { value = SUBURB }
var postcode = MutableLiveData<String>().apply { value = POSTCODE }
var limit = MutableLiveData<Int>().apply { value = LIMIT }

val filteredRows: LiveData<List<MyTable>> = 
    suburb.switchMap {

           //set suburb MutableLiveData
           var suburb = it

           postcode.switchMap {
              //set postcode MutableLiveData
              var postcode = it


            }

            limit.switchMap {
              //set limit MutableLiveData
              var limit = it


            }

    repository.getFilteredRows(suburb, postcode, limit)

} 

/// EDIT ANSWER ///

Using HashMap to pass multiple filters (Strings) to Dao SQl Query. Tested a returned what was expected, so confirming this works.

Foreseeable issue is when needing to pass Strings & Int etc, may have to refer back to passing as Strings only & then do parse.ToInt() etc on Int String Values

build HashMap in my Fragment to pass to MyViewModel

lateinit var myModel: LiveData<MyTable>

var filters = HashMap<String, String>()
filters.put("suburb", myModel.value!!.suburb)
filters.put("postcode", myModel.value!!.postcode)


 with(viewModel) {

        //pass my HashMap to my ViewModel for update/change/set on filters MutableLiveData HashMap variable
        setFilters(filters)

 }

MyViewModel Class

 //initilise filters MutableLiveData HashMap variable
 var filters = MutableLiveData<HashMap<String, String>>().apply { value = FILTERS }


 //function to update/change/set filters MutableLiveData HashMap variable
 //see setFilters(filters) used in above Fragment
 fun setFilters(_filters: HashMap<String, String>) {
    filters.value = _filters
 }


 //foreach on passed HashMap via switchMap{}
 val filtered: LiveData<List<MyTable>> = filters.switchMap {

    //initilise variables
    var suburb = ""
    var postcode = ""

    //foreach loop on HashCookie :)
    for (filter in it) {
        if(filter.key.equals("suburb")){
            suburb = filter.value
        }else if(filter.key.equals("postcode")) {
            postcode = filter.value
        }
    }

    //pass strings to Dao
    repository.getFiltered(suburb, postcode)

 }

//companion object
companion object {
    var FILTERS: HashMap<String, String>? = null
 }

Repository Class

//send variables to the Dao Interface
fun getFiltered(suburb: String?, postcode: String?) = dao.getFiltered(suburb, postcode)

Dao Interface

@Query("SELECT * FROM mytable WHERE suburb LIKE '%' || :suburb || '%' AND postcode LIKE '%' || :postcode || '%' ")
fun getFiltered(suburb: String?, postcode: String?): LiveData<List<MyTable>>

Upvotes: 1

Related Questions