Filtering Realm object in android

萝らか妹 提交于 2019-12-10 17:16:16

问题


So i've started to use Realm and everything works fine, well almost everything.

I'm using a MultiAutoCompleteTextView to select some user (RealmObject)

so here goes:

this is my Filter( inner class of my adapter)

private class UserFilter extends Filter {
    @Override
    protected FilterResults performFiltering(CharSequence constraint) {
        FilterResults filterResults = new FilterResults();
        if (constraint == null || constraint.length() == 0) {
            filterResults.values = mUsers;
            filterResults.count = mUsers.size();
        } else {
            final String lastToken = constraint.toString().toLowerCase();
            final List<User> list = new ArrayList<>();

            RealmQuery<User> query = realm.where(User.class);
            query.contains("nickname", lastToken, false);
            RealmResults<User> result = query.findAll();
            list.addAll(result);


            filterResults.values = list;
            filterResults.count = list.size();
        }
        return filterResults;
    }

    @Override
    protected void publishResults(CharSequence constraint, FilterResults results) {
        mFilteredUsers = (List<User>) results.values;
        if (results.count > 0) {
            notifyDataSetChanged();
        } else {
            notifyDataSetInvalidated();
        }
    }

And in my adapter: in the getView method:

EGCUser user = getItem(position);

holder.mName.setText(user.getNickname());

user is an invalid object, i've been trying so many different thing and everything failed. So I'm wondering what can I do the achieved that. I've got a lot of thread issue so maybe it's a problem with the inner class ?

Thanks

EDIT: in this situation, where am I supposed to do the Realm.getInstance()?

Right now, I pass a context in my adapter and i'm doing it in the constructor of the adapter, and i'm stocking the realm object in a variable.

EDIT2: I got it to work but I don't know if this is how we're supposed to do:

In my performFiltering I did this:

((Activity)mContext).runOnUiThread(new Runnable() {
                @Override
                public void run() {

                    final List<User> list = new ArrayList<>();
                    Realm realm = Realm.getInstance(mContext);
                    RealmQuery<User> query = realm.where(User.class);
                    query.contains("nickname", lastToken, false);
                    RealmResults<User> result1 = query.findAll();
                    list.addAll(result1);

                    filterResults.values = list;
                    filterResults.count = list.size();

                }
            });

But i'll this open for feedback.


回答1:


Christian from Realm here. Unfortunately Realm currently doesn't support the Filter class due to our Thread restrictions (and Filter does it's job on a background thread). We have it on our TODO however and you can follow progress here: https://github.com/realm/realm-android-adapters/issues/79

Until then you have two options:

1) Perform the filtering the the UI thread. If you don't have that many items in Realm or the query is relative simple, you will probably find that this is fast enough. We already have keyboard apps using Realm that does it this way.

2) Instead of returning proper Realm objects, read whatever data you need to display and return that from the performFiltering() method instead.




回答2:


I implemented a solution. The filter I did was responsible of help an AutocompleteTextView. The strategy consists of create a wrapper class that encapsulates the fields of the realm objects you want to show. Also, it should contains the primary key so then you can retrieve the full object.

This is an example of the "wrapper" class:

public class RealmWrapper{

  private long oid;
  private String representation;

  public RealmWrapper(long oid, String representation) {
    this.oid = oid;
    this.representation = representation;
  }

  public long getOid() {
    return this.oid;
  }

  public void setOid(long oid) {
    this.oid = oid;
  }

  public String getRepresentation() {
    return representation;
  }

  public void setRepresentation(String representation) {
    this.representation = representation;
  }

  @Override
  public String toString() {
    return representation;
  }
}

And when you extract the entities from Realm you copy the results to the wrapper:

 List<RealmWrapper> newObjects = new ArrayList<>();
 for( User entity : (RealmResults<User>) queryResults ){
     newObjects.add( new RealmWrapper(entity.getOid(), entity.getName()) );
 }

And finally, when you got the RealmViewAdapter from the view, you retrieve the original object:

User user = Realm.getInstance(context)
          .where(User.class)
          .contains("oid",adapter.getOid)
          .firstResult(); 

I hope this help you!



来源:https://stackoverflow.com/questions/30162431/filtering-realm-object-in-android

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!