通过带有存储库的ViewModel将多个过滤器传递到Android Room Dao SQL查询

时间:2019-08-13 07:49:43

标签: android-room dao android-livedata mutablelivedata

我正在使用以下内容将数据库行提取到我的适配器,但是我想使用“ LIKE”和/或“ WHERE”以及基本上所有的sql查询过滤器类型从多过滤的单个查询中返回行,我可以通过MutableLiveData<String>()进行过滤;

最终结果将类似于...

@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>>

如下所示,当前方式只能通过一个过滤器变量。

ViewModel类

 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
 }

存储库类

class Repository private constructor(private val dao: Dao)

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

Dao界面

@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>>

我尝试通过运气基本的var字符串,似乎只有MutableLiveData是通过ViewModelRepository

来将变量传递给Dao的方法。

1 个答案:

答案 0 :(得分:0)

** 请参见下面的编辑 **

至少可以说是不理想的,实际上不推荐,但是,当前的解决方法是通过多个MutableLiveData变量“循环”

ViewModel类

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)

} 

///编辑答案///

使用HashMap将多个过滤器(字符串)传递给Dao SQl查询。 测试了返回预期的结果,因此确认此方法有效。

可预见的问题是,当需要传递Strings和Int等时,可能不得不将其仅引用回传递,然后对Int String值进行parse.ToInt()等

在我的片段中构建HashMap以传递给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类

 //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
 }

存储库类

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

Dao界面

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