MVVM Recyclerview Livedata会议室SearchView [英] MVVM Recyclerview Livedata Room SearchView
问题描述
我正在使用room, mvvm, livedata
创建数据库应用.我已经用一些数据预填充了它.现在我有两个选择,要么是我将通过recyclerview
打开应用程序时显示该预先填充的数据,要么是当我在recyclerView中使用SearchView
搜索它时显示该数据.
问题是当我搜索特定项目时,当我说完这句话并且尝试返回resView时,它将显示该项目为空,或者它始终停留在该项目上.我想尝试实时,例如:当我只输入一个字母时,它显示所有建议都属于字母,我只想使用livedata
更新
我尝试了什么?
1->我已经尝试了与liveData
一起使用的switchMap
,但是我必须刷新活动才能获取列表.
2->我尝试过resView过滤器,该过滤器不起作用,因为我正在使用livedata来更新我的UI,并且在没有livedata
的情况下对其进行了定期尝试,但它也仍然不起作用.
3->我尝试了常规的editText
只是为了尝试,但是由于遇到相同的问题我没有发现它有用,我的主要重点是searchView
RecyclerView代码 具有可过滤的内容或只是忽略可过滤的部分,根本不是一个很好的尝试
I am making database app using room, mvvm, livedata
. I have Prepopulated it with some data. Now i have two options either i am going to show that prepoulated data when app turns on via recyclerview
or show it when i search it using SearchView
inside recyclerView.
The Problem is when i search for particular item, itw shows that item when i complete my word and when i try to go back either my resView back empty or it always stays on that item. i wanna try sometime realtime like: when i enter only one alphabet it show all the suggestions belongs to alphabet, i only want to update with livedata
What i have try?
1-> I have already tried switchMap
which worked with liveData
but i have to refresh my activity in order to get back my list.
2-> I have tried resView filter which didn't worked because i am using livedata to update my UI and also give it regular try without livedata
it still didn't work either.
3-> I Have tried regular editText
just to try but i didn't find it useful as facing same problem, my main focus was on searchView
RecyclerView code with filterable or just ignore filterable part it wasn't good try at all
class MyAdapter(
private var context: Context,
private var dataList: List<SearchPojo>
) : RecyclerView.Adapter<MyAdapter.BaseViewHolder<*>>(), Filterable {
private var exampleListFull: List<SearchPojo>? = null
init {
exampleListFull = ArrayList(dataList)
}
companion object {
const val SEARCH_TYPE = 1
}
abstract class BaseViewHolder<T>(view: View) : RecyclerView.ViewHolder(view) {
abstract fun bind(t: T)
}
inner class SearchViewHolder(view: View) : BaseViewHolder<SearchPojo>(view) {
private val userID: TextView = view.findViewById(R.id.idSearch)
private val userName: TextView = view.findViewById(R.id.nameSearch)
private val userPos: TextView = view.findViewById(R.id.positionSearch)
override fun bind(t: SearchPojo) {
userID.text = t.id
userName.text = t.userName
userPos.text = t.position
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseViewHolder<*> {
return when (viewType) {
SEARCH_TYPE -> {
val view =
LayoutInflater.from(context).inflate(R.layout.layout_show_data, parent, false)
SearchViewHolder(view)
}
else -> {
throw IllegalAccessException("In valid View Type")
}
}
}
override fun getItemCount(): Int {
return dataList.size
}
override fun onBindViewHolder(holder: BaseViewHolder<*>, position: Int) {
val element = dataList[position]
when (holder) {
is SearchViewHolder -> {
holder.bind(element)
}
}
}
override fun getItemViewType(position: Int): Int {
return when (dataList[position]) {
is SearchPojo -> SEARCH_TYPE
else -> throw IllegalAccessException()
}
}
override fun getFilter(): Filter {
return exampleFilter
}
private var exampleFilter = object : Filter() {
override fun performFiltering(constraint: CharSequence?): FilterResults {
val filteredList = ArrayList<SearchPojo>()
if (constraint == null || constraint.isEmpty()) {
filteredList.addAll(exampleListFull as Iterable<SearchPojo>)
} else {
val filterPattern = constraint.toString().toLowerCase().trim { it <= ' ' }
for (item in exampleListFull!!) {
if (item.userName.toLowerCase().contains(filterPattern)) {
filteredList.add(item)
}
}
}
val results = FilterResults()
results.values = filteredList
return results
}
override fun publishResults(constraint: CharSequence, results: FilterResults) {
dataList.clear()
dataList.addAll(results.values as List<SearchPojo>)
notifyDataSetChanged()
}
}
}
主要活动
class MainActivity : AppCompatActivity() {
lateinit var searchViewModel: SearchViewModel
lateinit var myAdapter: MyAdapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
if (!::searchViewModel.isInitialized) {
searchViewModel = ViewModelProviders.of(this)[SearchViewModel::class.java]
searchViewModel.getAll().observe(this, Observer {
myAdapter(it)
})
}
searchItems.addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(s: Editable?) {
}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
nameFromDb(s.toString())
}
})
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.search_item, menu)
val searchItem = menu!!.findItem(R.id.search_menu)
val searchView = searchItem.actionView as SearchView
searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
override fun onQueryTextSubmit(query: String?): Boolean {
return false
}
override fun onQueryTextChange(newText: String?): Boolean {
myAdapter.getFilter().filter(newText)
return true
}
})
return super.onCreateOptionsMenu(menu)
}
override fun onOptionsItemSelected(item: MenuItem?): Boolean {
when (item!!.itemId) {
R.id.refresh -> {
val intent = Intent(this, MainActivity::class.java)
startActivity(intent)
}
}
return true
}
private fun nameFromDb(searchTxt: String) {
searchViewModel = ViewModelProviders.of(this)[SearchViewModel::class.java]
searchViewModel.items.observe(this, object : Observer<List<SearchPojo>> {
override fun onChanged(t: List<SearchPojo>?) {
if (t == null) {
return
}
myAdapter(t)
}
})
searchViewModel.searchIt(searchTxt)
}
private fun myAdapter(t: List<SearchPojo>) {
searchResultResView.apply {
layoutManager = LinearLayoutManager(context)
myAdapter = MyAdapter(this@MainActivity, t)
adapter = myAdapter
}
}
}
ViewModel
lass SearchViewModel(application: Application) :
AndroidViewModel(application) {
private val repo: SearchRepo = SearchRepo(application)
private val _searchItem : MutableLiveData<String> = MutableLiveData()
val items : LiveData<List<SearchPojo>> = Transformations.switchMap(_searchItem) { myItems ->
repo.searchItem(myItems)
}
init {
_searchItem.value = ""
}
fun searchIt(items: String) {
_searchItem.value = items
}
fun getAll() = repo.allSearch()
}
存储库
class SearchRepo(application: Application) {
private val searchDao: SearchDao
init {
val db = SearchDb.instance(application)
searchDao = db.searchDao()
}
fun searchItem(id: String): LiveData<List<SearchPojo>> {
return searchDao.searchViaID(id)
}
fun allSearch() : LiveData<List<SearchPojo>> {
return searchDao.allSearch()
}
}
Dao
@Dao
abstract class SearchDao : BaseDao<SearchPojo> {
@Query("Select * from SearchPojo")
abstract fun allSearch(): LiveData<List<SearchPojo>>
@Query("Select * from SearchPojo where userName Like :userNameSearch or LOWER(userName) like LOWER(:userNameSearch)")
abstract fun searchViaID(userNameSearch: String) : LiveData<List<SearchPojo>>
@Insert
abstract override fun insert(searchPojo: SearchPojo)
}
推荐答案
请像这样更改您的@Dao类
Please change your @Dao class like this
@Dao
abstract class SearchDao : BaseDao<SearchPojo> {
@Query("Select * from SearchPojo")
abstract fun allSearch(): LiveData<List<SearchPojo>>
@Query("Select * from SearchPojo where userName GLOB '*' || :userNameSearch|| '*'")
abstract fun searchViaID(userNameSearch: String) : LiveData<List<SearchPojo>>
@Insert
abstract override fun insert(searchPojo: SearchPojo)
}
这篇关于MVVM Recyclerview Livedata会议室SearchView的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!