realm-android-adapters
realm-android-adapters copied to clipboard
Support filterable interface on RealmBaseAdapter
Moved from https://github.com/realm/realm-java/issues/646
As pr. this discussion on Google Groups: https://groups.google.com/forum/#!topic/realm-java/KMwalH1sD3Y
This will require being able to move objects between threads. Will at least require https://github.com/realm/realm-java/issues/503 first
This is a good example for using Filter
and Filterable
with RealmRecyclerViewAdapter
http://stackoverflow.com/questions/40630322/how-to-implement-filterable-in-realmrecyclerviewadapter/40632613#40632613
@Zhuinden, I followed step by step your suggestion on SO and tried to implement it.
Realm versions tested: 5.7.0 and 5.8.0
Devices tested:
- OnePlus 6 A6003 - Android Pie 28
- LGE LG-K371 - Android Nougat 24
- Google Pixel 2 (Genymotion emulator, v. 2.12.1) - Android Oreo 26
In my adapter extending RealmRecyclerViewAdapter
and implementing Filterable
I have:
fun filterResults(text: String) {
val query = fragment.getRealm().where(ChatRoom::class.java)
if(!text.toLowerCase().trim().isBlank()) {
query.contains("roomName", text, Case.INSENSITIVE)
}
updateData(
query.findAllAsync().also {
it.addChangeListener { t, _ ->
// listener added to do some operations after data set change
}
}
)
}
override fun getFilter(): Filter {
return ChatRoomFilter(this, fragment)
}
private class ChatRoomFilter(val adapter: ChatRoomsAdapter, val fragment: ChatRoomsFragment): Filter() {
override fun performFiltering(constraint: CharSequence?): FilterResults {
return FilterResults()
}
override fun publishResults(constraint: CharSequence?, results: FilterResults?) {
adapter.filterResults(constraint.toString())
}
}
And when my search listener gets triggered from the TextWatcher
I run adapter.filter.filter(query)
where query
is my search string.
Debugging both my code and Realm library code I cannot see anything suspicious: I mean that in Realm code the notifyDataSetChanged()
within updateData()
method is correctly called, but no change in the UI happens.
Do you have any suggestions?
Is it possible that from your SO answer some changes in Realm may have altered the outcome?
No I think this should work as long as you are using realm-android-adapters:3.0.0
I didn't notice the change in release. I was still using the 2.1.1. Anyways, even after updating to 3.0.0 nothing...
Any idea/suggestion, guys?
I really think that for me the problem is the updateData()
method.
Looking at the source code I see this line RealmRecyclerViewAdapter.java, l. 205: this.adapterData = data;
, within the updateData()
method:
public void updateData(@Nullable OrderedRealmCollection<T> data) {
if (hasAutoUpdates) {
if (isDataValid()) {
//noinspection ConstantConditions
removeListener(adapterData);
}
if (data != null) {
addListener(data);
}
}
this.adapterData = data;
notifyDataSetChanged();
}
When I first used RecyclerView I often forgot that changing the instance of the collection underneath the adapter was wrong, and I always used addAll()
method to maintain the same collection instance and to keep receiving the UI updates from the notify...()
methods of the adapter.
I don't understand why this should behave differently from my rookie mistakes, since this line clearly replaces the original collection instance with a new one.
But I'm sure I'm missing something...
You're using getData()
inside onBindViewHolder
right?
Lifesaver!!! Nope, I was using the collection passed as argument to the adapter, just like any other RecView adapter.
So, basically, what I didn't get is that with RealmRecyclerViewAdapter
s I must always access the collection with getData()
, right?
Yeah, pretty much, otherwise you'll run into the problem that you won't access the new dataset after using updateData()
(this might sound like a familiar problem 😛 )
Again, thank you so much!