Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support filterable interface on RealmBaseAdapter #79

Open
cmelchior opened this issue Jan 30, 2017 · 9 comments
Open

Support filterable interface on RealmBaseAdapter #79

cmelchior opened this issue Jan 30, 2017 · 9 comments

Comments

@cmelchior
Copy link
Contributor

cmelchior commented Jan 30, 2017

Moved from realm/realm-java#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 realm/realm-java#503 first


@Zhuinden
Copy link

Zhuinden commented Mar 9, 2017

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

@maxbaldrighi
Copy link

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

@Zhuinden
Copy link

No I think this should work as long as you are using realm-android-adapters:3.0.0

@maxbaldrighi
Copy link

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?

@maxbaldrighi
Copy link

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

@Zhuinden
Copy link

You're using getData() inside onBindViewHolder right?

@maxbaldrighi
Copy link

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 RealmRecyclerViewAdapters I must always access the collection with getData(), right?

@Zhuinden
Copy link

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

@maxbaldrighi
Copy link

Again, thank you so much!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants