Как использовать SearchView с LiveData и ViewModel в комнате - PullRequest
0 голосов
/ 14 января 2020

Я хочу использовать SearchView для поиска некоторого элемента в комнате базы данных, и у меня есть проблема с этим, потому что я не могу использовать getFilter в RecyclerViewAdapter, потому что у меня 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>>

}

1 Ответ

0 голосов
/ 15 января 2020

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

Этот метод в вашем дао должен возвращать LiveData<List<ProductEntity>>, а не LiveData<List<String>>, потому что этот запрос выбирает все (*) от сущности и не указанный столбец c.

аналогично (@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
        }


    }

Репозиторий

... другим имеющимся у вас способом добавьте следующее:

fun allProducts():LiveData<List<ProductEntity>>=productDao.getListAllProducts()
fun allProductsByNames(name:String):LiveData<List<ProductEntity>>=productDao.getListAllByName(name)

В вашей активности или фрагменте, где у вас есть адаптер повторного просмотра

внутри onCreate () (если это действие)

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)

Надеюсь, это поможет

С уважением,

...