如何在 Room 中使用带有 LiveData 和 ViewModel 的 SearchView
How to use SearchView with LiveData and ViewModel in Room
我想使用 SearchView 在 room db 中搜索一些元素,我对此有疑问,因为我不能在 RecyclerViewAdapter 中使用 getFilter,因为我有 ViewModel,也许谁知道如何在一个项目中组合所有这些元素。
我搜索使用 Transormations.switchMap 的一种方式。但是我连接不上。
ProductViewModel
class ProductViewModel(application: Application) : AndroidViewModel(application) {
private val repository: ProductRepository
val allProducts: LiveData<List<ProductEntity>>
private val searchStringLiveData = MutableLiveData<String>()
init {
val productDao = ProductsDB.getDatabase(application, viewModelScope).productDao()
repository = ProductRepository(productDao)
allProducts = repository.allProducts
searchStringLiveData.value = ""
}
fun insert(productEntity: ProductEntity) = viewModelScope.launch {
repository.insert(productEntity)
}
val products = Transformations.switchMap(searchStringLiveData) { string ->
repository.getAllListByName(string)
}
fun searchNameChanged(name: String) {
searchStringLiveData.value = name
}
}
ProductDao
interface ProductDao {
@Insert(onConflict = OnConflictStrategy.IGNORE)
suspend fun insertProduct(productEntity: ProductEntity)
@Query("SELECT * from products")
fun getListAllProducts(): LiveData<List<ProductEntity>>
@Query("DELETE FROM products")
suspend fun deleteAll()
@Query("SELECT * FROM products where product_name_ent LIKE :name or LOWER(product_name_ent) like LOWER(:name)")
fun getListAllByName(name: String):LiveData<List<String>>
}
ProductDao
@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>>
你 dao 中的这个方法应该 return LiveData<List<ProductEntity>>
而不是 LiveData<List<String>>
,因为这个查询从实体中选择 everything (*) 不是特定的列。
它类似于 (@Query("SELECT * from products") fun getListAllProducts():LiveData<List<ProductEntity>>
)
ProductViewModel
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
}
}
Repository
...使用您拥有的其他方法,添加以下内容:
fun allProducts():LiveData<List<ProductEntity>>=productDao.getListAllProducts()
fun allProductsByNames(name:String):LiveData<List<ProductEntity>>=productDao.getListAllByName(name)
In Your Activity Or Fragment Where you have the recyclerview adapter
在 onCreate() 内部(如果它是 activity)
viewModel.allProducts.observe(this,Observer{products->
//populate your recyclerview here
})
或
onActivityCreated(if it is a fragment)
viewModel.allProducts.observe(viewLifecycleOwner,Observer{products->
//populate your recyclerview here
})
现在给 searchView 设置一个侦听器,每次用户提交查询时,调用 viewModel.searchNameChanged(// pass the new value)
希望对您有所帮助
此致,
我想使用 SearchView 在 room db 中搜索一些元素,我对此有疑问,因为我不能在 RecyclerViewAdapter 中使用 getFilter,因为我有 ViewModel,也许谁知道如何在一个项目中组合所有这些元素。
我搜索使用 Transormations.switchMap 的一种方式。但是我连接不上。
ProductViewModel
class ProductViewModel(application: Application) : AndroidViewModel(application) {
private val repository: ProductRepository
val allProducts: LiveData<List<ProductEntity>>
private val searchStringLiveData = MutableLiveData<String>()
init {
val productDao = ProductsDB.getDatabase(application, viewModelScope).productDao()
repository = ProductRepository(productDao)
allProducts = repository.allProducts
searchStringLiveData.value = ""
}
fun insert(productEntity: ProductEntity) = viewModelScope.launch {
repository.insert(productEntity)
}
val products = Transformations.switchMap(searchStringLiveData) { string ->
repository.getAllListByName(string)
}
fun searchNameChanged(name: String) {
searchStringLiveData.value = name
}
}
ProductDao
interface ProductDao {
@Insert(onConflict = OnConflictStrategy.IGNORE)
suspend fun insertProduct(productEntity: ProductEntity)
@Query("SELECT * from products")
fun getListAllProducts(): LiveData<List<ProductEntity>>
@Query("DELETE FROM products")
suspend fun deleteAll()
@Query("SELECT * FROM products where product_name_ent LIKE :name or LOWER(product_name_ent) like LOWER(:name)")
fun getListAllByName(name: String):LiveData<List<String>>
}
ProductDao
@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>>
你 dao 中的这个方法应该 return LiveData<List<ProductEntity>>
而不是 LiveData<List<String>>
,因为这个查询从实体中选择 everything (*) 不是特定的列。
它类似于 (@Query("SELECT * from products") fun getListAllProducts():LiveData<List<ProductEntity>>
)
ProductViewModel
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
}
}
Repository
...使用您拥有的其他方法,添加以下内容:
fun allProducts():LiveData<List<ProductEntity>>=productDao.getListAllProducts()
fun allProductsByNames(name:String):LiveData<List<ProductEntity>>=productDao.getListAllByName(name)
In Your Activity Or Fragment Where you have the recyclerview adapter
在 onCreate() 内部(如果它是 activity)
viewModel.allProducts.observe(this,Observer{products->
//populate your recyclerview here
})
或
onActivityCreated(if it is a fragment)
viewModel.allProducts.observe(viewLifecycleOwner,Observer{products->
//populate your recyclerview here
})
现在给 searchView 设置一个侦听器,每次用户提交查询时,调用 viewModel.searchNameChanged(// pass the new value)
希望对您有所帮助
此致,