Solution 1 :
i’m not use the filter in the adapter,but i think may be u can use the list.filter and setThe NewData with the DiffUtil? although it may be not the best solution
Problem :
I am trying to filter the list in RecyclerView by EditText. In Activity, passing the response in the adapter object, which is getting from the ViewModel class. And in the adapter, the filter method is written. Overall the Search Filter from EditText is not working. Below the code is written I am not sure how can I resolve this problem.
Project having manly an Activity,Adapter, XML file, and the ViewModel class.
fragment_availabletender
This page is having EditText & RecyclerView.
<EditText
android_id="@+id/editMobileNo"
android_layout_width="match_parent"
android_layout_height="50dp"
android_padding="0dp"
android_background="@drawable/login_edittext"
android_ems="10"
android_hint="Search Tender"
android_gravity="center"
android_drawableLeft="@drawable/search_3_24"
android_layout_below="@+id/tendertext"
android_paddingLeft="50dp"
>
</EditText>
<androidx.recyclerview.widget.RecyclerView
android_id="@+id/tender_list"
android_layout_width="match_parent"
android_layout_height="match_parent"
android_color="@color/cardview_light_background"
android_padding="6dp"
android_background="@null"
android_scrollbars="vertical"
android_layout_marginTop="10dp"
android_layout_below="@+id/text1"
app_layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
/>
Model Class
This class is having model
data class TenderProperty(
val id: String,
@Json(name = "img_src") val imgSrcUrl: String,
val type: String,
val price: Double
)
ViewModel
Here response is getting
class NotificationViewModel : ViewModel() {
val response: LiveData<List<TenderProperty>>
get() = _response
private var _responseByArray = ArrayList<TenderProperty>()
val responseByArray: List<TenderProperty>
get() = _responseByArray
private val _navigateToSelectedProperty = MutableLiveData<TenderProperty>()
val navigateToSelectedProperty: LiveData<TenderProperty>
get() = _navigateToSelectedProperty
// Create a Coroutine scope using a job to be able to cancel when needed
private var viewModelJob = Job()
private val coroutineScope = CoroutineScope(viewModelJob + Dispatchers.Main )
init {
getTenderRealEstateProperties()
}
private fun getTenderRealEstateProperties() {
coroutineScope.launch {
// Get the Deferred object for our Retrofit request
var getPropertiesDeferred = TenderApi.retrofitService.getProperties()
try {
// this will run on a thread managed by Retrofit
val listResult = getPropertiesDeferred.await()
_responseByArray= listResult as ArrayList<TenderProperty>
Log.d("respbyary",responseByArray.toString())
} catch (e: Exception) {
_response.value = ArrayList()
Log.d("class",responseByArray.toString())
}
}
}
This is the Adapter class
class ListTenderAdapter(context: Context, var tender: List<TenderProperty>) : ListAdapter<TenderProperty, ListTenderAdapter.TenderPropertyViewHolder>(DiffCallback),Filterable {
var originalData=tender
var filteredData = ArrayList<TenderProperty>()
//dought22
class TenderPropertyViewHolder(private var binding: TenderListViewBinding) : RecyclerView.ViewHolder(binding.root) {
fun bind(tenderProperty: TenderProperty) {
binding.property = tenderProperty
binding.executePendingBindings()
}
}
companion object DiffCallback : DiffUtil.ItemCallback<TenderProperty>()
{
override fun areItemsTheSame(oldItem: TenderProperty, newItem: TenderProperty): Boolean {
return oldItem === newItem
}
override fun areContentsTheSame(oldItem: TenderProperty, newItem: TenderProperty): Boolean {
return oldItem.id == newItem.id
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TenderPropertyViewHolder {
return TenderPropertyViewHolder(TenderListViewBinding.inflate(LayoutInflater.from(parent.context)))
}
override fun onBindViewHolder(holder: TenderPropertyViewHolder, position: Int) {
val tenderProperty = getItem(position)
holder.bind(tenderProperty)
}
override fun getFilter(): Filter {
return object : Filter() {
override fun performFiltering(constraint: CharSequence?): FilterResults {
var filteredList = ArrayList<TenderProperty>()
if (constraint.isNullOrBlank()) {
filteredData.addAll(originalData)
}
else {
for (data in originalData) {
if (
data.id.toLowerCase().contains(constraint.toString().toLowerCase())||
data.price.toString().toLowerCase().contains(constraint.toString().toLowerCase())||
data.type.toLowerCase().contains(constraint.toString().toLowerCase()))
{
filteredList.add(data)
} }
}
val filterResults = FilterResults()
filterResults.values = filteredList
return filterResults
}
override fun publishResults(constraint: CharSequence, results: FilterResults) {
filteredData.clear()
filteredData.addAll(results.values as ArrayList<TenderProperty>)
notifyDataSetChanged()
}
}}}
This is the Activity
class TenderListActivity:AppCompatActivity() {
lateinit var adapter: ListTenderAdapter
lateinit var search:EditText
private lateinit var binding: FragmentAvailabletenderBinding
private val viewModel: NotificationViewModel by lazy {
ViewModelProviders.of(this).get(NotificationViewModel::class.java)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.fragment_availabletender)
binding = DataBindingUtil.setContentView<FragmentAvailabletenderBinding>(
this,
R.layout.fragment_availabletender
)
search = binding.editMobileNo
val divider = DividerItemDecoration(applicationContext, DividerItemDecoration.VERTICAL)
binding.tenderList.addItemDecoration(divider)
setupRecyclerView()
initViewModel()
search()
backButton()
}
private fun setupRecyclerView() {
binding.tenderList.addItemDecoration(MarginItemDecoration(5))
adapter = ListTenderAdapter(this, viewModel.responseByArray)
binding.tenderList.setAdapter(adapter)
}
private fun initViewModel() {
viewModel.response.observe(this, Observer {
adapter.submitList(it)
})
}
private fun backButton()
{
binding.backbtn.setOnClickListener(View.OnClickListener {
val backbtn: Intent = Intent(this,MainActivity::class.java)
startActivity(backbtn)
})
}
private fun search()
{
search.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {
}
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
adapter.getFilter().filter(s.toString())
}
override fun afterTextChanged(s: Editable) {
}
})
}}
Comments
Comment posted by anish sethiya
While writing list. filter, It is getting an error.
Comment posted by Silence
i mean the data.filter not the recycleview.filter . use the filter to filter the data what you want .then reset the data and notify
Comment posted by anish sethiya
I used the filter but it is not working, maybe the problem is somewhere else.In below comment I the filter code what I added.
Comment posted by anish sethiya
else { originalData.filter { it.id.contains(queryString) || it.imgSrcUrl.contains(queryString) || it.price.toString().contains(queryString) } filteredData.addAll(originalData) }