如何在 Room 中将 SearchView 与 LiveData 和 ViewModel 结合使用

Kos*_*ysh 0 android viewmodel kotlin searchview

我想使用 SearchView 搜索房间数据库中的某个元素,但我遇到了一个问题,因为我无法在 RecyclerViewAdapter 中使用 getFilter 因为我有 ViewModel 也许谁知道如何将所有这些元素组合到一个项目中。
\n我搜索一种使用 Transormations.switchMap 的方法。但我无法连接它们。

\n\n
\n

产品视图模型

\n
\n\n
class ProductViewModel(application: Application) : AndroidViewModel(application) {\n    private val repository: ProductRepository\n\n    val allProducts: LiveData<List<ProductEntity>>\n    private val searchStringLiveData = MutableLiveData<String>()\n\n    init {\n        val productDao = ProductsDB.getDatabase(application, viewModelScope).productDao()\n        repository = ProductRepository(productDao)\n        allProducts = repository.allProducts\n        searchStringLiveData.value = ""\n    }\n\n    fun insert(productEntity: ProductEntity) = viewModelScope.launch {\n        repository.insert(productEntity)\n    }\n\n\n    val products = Transformations.switchMap(searchStringLiveData) { string ->\n        repository.getAllListByName(string)\n\n    }\n\n    fun searchNameChanged(name: String) {\n        searchStringLiveData.value = name\n    }\n\n\n\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n

产品道

\n
\n\n
interface ProductDao {\n\n    @Insert(onConflict = OnConflictStrategy.IGNORE)\n    suspend fun insertProduct(productEntity: ProductEntity)\n\n    @Query("SELECT * from products")\n    fun getListAllProducts(): LiveData<List<ProductEntity>>\n\n\n    @Query("DELETE FROM products")\n    suspend fun deleteAll()\n\n    @Query("SELECT * FROM products where product_name_ent LIKE :name or LOWER(product_name_ent) like LOWER(:name)")\n    fun  getListAllByName(name: String):LiveData<List<String>>\n\n}\n
Run Code Online (Sandbox Code Playgroud)\n

小智 6

产品道

@Query("SELECT * FROM products where product_name_ent LIKE :name or LOWER(product_name_ent) like LOWER(:name)")
            fun  getListAllByName(name: String):LiveData<List<ProductEntity>>
Run Code Online (Sandbox Code Playgroud)

dao 中的此方法应该返回LiveData<List<ProductEntity>>而不是返回,因为此查询从实体中LiveData<List<String>>选择所有内容(*),而不是特定列。

它类似于( @Query("SELECT * from products") fun getListAllProducts():LiveData<List<ProductEntity>>)

产品视图模型

    class ProductViewModel(application: Application) : AndroidViewModel(application) {
        private val repository: ProductRepository
        init {
            val productDao = ProductsDB.getDatabase(
                application,
                viewModelScope
            ).productDao()
            repository = ProductRepository(productDao)
        }


        private val searchStringLiveData = MutableLiveData<String>("") //we can add initial value directly in the constructor
        val allProducts: LiveData<List<ProductEntity>>=Transformations.switchMap(searchStringLiveData)
        {
            string->
            if (TextUtils.isEmpty(string)) {
                repository.allProducts()
            } else {
                repository.allProductsByName(string)
            }
        }


        fun insert(productEntity: ProductEntity) = viewModelScope.launch {
            repository.insert(productEntity)
        }

        fun searchNameChanged(name: String) {
            searchStringLiveData.value = name
        }


    }
Run Code Online (Sandbox Code Playgroud)

存储库

...使用您拥有的其他方法,添加以下内容:

fun allProducts():LiveData<List<ProductEntity>>=productDao.getListAllProducts()
fun allProductsByNames(name:String):LiveData<List<ProductEntity>>=productDao.getListAllByName(name)
Run Code Online (Sandbox Code Playgroud)

在您的 Activity 或 Fragment 中,您拥有 recyclerview 适配器

onCreate() 内部(如果它是一个 Activity)

viewModel.allProducts.observe(this,Observer{products->
//populate your recyclerview here
})
Run Code Online (Sandbox Code Playgroud)

或者

onActivityCreated(if it is a fragment)
       viewModel.allProducts.observe(viewLifecycleOwner,Observer{products->
    //populate your recyclerview here
    })
Run Code Online (Sandbox Code Playgroud)

现在为 searchView 设置一个监听器,每次用户提交查询时,调用viewModel.searchNameChanged(// pass the new value)

希望这可以帮助

问候,