Search code examples
javaandroidrealm

Invoking updateData on a RealmRecyclerViewAdapter is not actually updating the data


I am trying to use a SearchView to filter a list provided by a RealmRecyclerViewAdapter. I have tried several things suggested here on StackOverflow, including this: EpicPandaForce's suggestion

to no avail. When I get to here: updateData(new realm query), nothing happens.

Here is my code. I started with Lucas Urbas's Material Master/Detail Case Study, and started adding things to it to help myself learn how. Inside the PeopleFragment, I modified setUpToolbar and setUpRecyclerView methods like this:

private void setUpToolbar() {
    if (DEBUG) Log.i(TAG, "Reached setUpToolbar") ;
    CustomAppBar appBar = ((MainActivity) getActivity()).getCustomAppBar() ;
    appBar.setTitle(getString(R.string.fragment_people__title)) ;
    appBar.setMenuRes(R.menu.people_general, R.menu.people_specific, R.menu.people_merged) ;

    // Set up search
    searchItem = appBar.getToolbarSpecific().getMenu().findItem(R.id.menu_people__search) ;
    searchView = (SearchView) searchItem.getActionView() ;
    searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
        @Override
        public boolean onQueryTextSubmit(String query) {
            if(DEBUG) Log.i(TAG, "Reached onQueryTextSubmit") ;
            adapter.updateData(realm.where(Person.class).equalTo("userId", userid).contains("name", query).findAll()) ;
            return true ;
            //return false;
        }

        @Override
        public boolean onQueryTextChange(String newText) {
            if(DEBUG) Log.i(TAG, "Reached onQueryTextChange") ;
            adapter.updateData(realm.where(Person.class).equalTo("userId", userid).contains("name", newText).findAll()) ;
            return true ;
            //return false;
        }
    }) ;

    // Set up menu item click listener
    appBar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
        @Override
        public boolean onMenuItemClick(MenuItem item) {
            if (DEBUG) Log.i(TAG, "Reached onMenuItemClick") ;
            // handle selection of action bar items
            switch (item.getItemId()) {
                case R.id.menu_people__add:
                    presenter.clickAddPerson() ;
                    return true ;
                case R.id.menu_people__search:
                    return true ;
                case R.id.menu_people__settings:
                    presenter.clickSettings() ;
                    return true ;
                case R.id.menu_people__logout:
                    sessionManager.logoutUser() ;
                    return true ;
            }
            return false ;
        }
    }) ;
} // end of setUpToolbar method


private void setUpRecyclerView() {
    if (DEBUG) Log.i(TAG, "Reached setUpRecyclerView") ;

    recyclerView.setHasFixedSize(true) ;

    final LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity()) ;
    layoutManager.setOrientation(LinearLayoutManager.VERTICAL) ;
    recyclerView.setLayoutManager(layoutManager) ;
    recyclerView.setEmptyView(emptyView) ;

    adapter = new PeopleAdapter(realm.where(Person.class).equalTo("userId", userid).findAll()) ;
    adapter.setOnPersonClickListener(new PersonView.OnPersonClickListener() {
        @Override
        public void onPersonClick(Person person) {
            presenter.clickPerson(person) ;
        }

        @Override
        public void onPersonActionClick(final Person person) {
            presenter.clickPersonAction(person) ;

            // ToDo: this should be in the presenter, but I don't have realm in there yet
            final Person newFave = realm.where(Person.class)
                    .equalTo("id", person.getId())
                    .findFirst() ;
            realm.executeTransaction(new Realm.Transaction() {
                @Override
                public void execute(Realm realm) {
                    newFave.setIsFavorite(!person.getIsFavorite()) ;
                }
            }) ;
        }
    }) ;

    recyclerView.setAdapter(adapter) ;

} // end of setUpRecyclerView method

And here is most of the PeopleAdapter:

class PeopleAdapter
    extends RealmRecyclerViewAdapter<Person, PeopleAdapter.PersonViewHolder> {

private final String TAG = "PeopleAdapter" ;
private final boolean DEBUG = true ;

private OrderedRealmCollection<Person> peopleList ;
private PersonView.OnPersonClickListener onPersonClickListener ;

static class PersonViewHolder extends RecyclerView.ViewHolder{

    PersonView personView ;

    PersonViewHolder(PersonView personView) {
        super(personView) ;
        this.personView = personView ;
    }
} // end of PersonViewHolder class


// Constructor
PeopleAdapter(OrderedRealmCollection<Person> data) {
    super(data, true, true) ; // data, autoUpdate, updateOnModification
    setHasStableIds(true) ;
    this.peopleList = data ;
}

void setOnPersonClickListener(PersonView.OnPersonClickListener onPersonClickListener) {
    this.onPersonClickListener = onPersonClickListener ;
}


@Override
public PeopleAdapter.PersonViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    PersonView view = (PersonView) LayoutInflater.from(parent.getContext())
                                .inflate(R.layout.item_view_person, parent, false) ;
    return new PersonViewHolder(view) ;
}


@Override
public void onBindViewHolder(PersonViewHolder holder, int position) {
    holder.personView.setUser(peopleList.get(position)) ;
    holder.personView.setOnPersonClickListener(onPersonClickListener) ;
}


@Override
public int getItemCount() {
    // If the peopleList is null, return 0, otherwise return the number of items in the list
    return peopleList == null ? 0 : peopleList.size() ;
}

I had log messages everywhere, but I took most of them out to make it easier to read. Basically, whether I try it this way, or try it with adapter implementing filterable, it gets right up to the updateData method without crashing, throwing an exception or indicating any problems at all, but it does nothing. The SearchView comes up, the text is entered and becomes part of the new query, the query is handed over to updateData, and...nothing.

Realm plugin 4.2.0, AndroidStudio 2.3.3, target sdk 25, Samsung Galaxy S2 running Android 7.0

I hope someone out there can help, as I tried the answers already given for questions like mine and I am baffled. Thank you


Solution

  • Don't have a peopleList variable in your RealmRecyclerViewAdapter, use getData().


    EDIT: This is what your adapter should look like:

    class PeopleAdapter
            extends RealmRecyclerViewAdapter<Person, PeopleAdapter.PersonViewHolder> {
        private final String TAG = "PeopleAdapter" ;
        private final boolean DEBUG = true ;
    
        private PersonView.OnPersonClickListener onPersonClickListener ;
    
        static class PersonViewHolder extends RecyclerView.ViewHolder{
            PersonView personView ;
            PersonViewHolder(PersonView personView) {
                super(personView) ;
                this.personView = personView ;
            }
        } // end of PersonViewHolder class
    
    
        // Constructor
        PeopleAdapter(OrderedRealmCollection<Person> data) {
            super(data, true, true) ; // data, autoUpdate, updateOnModification
        }
    
        void setOnPersonClickListener(PersonView.OnPersonClickListener onPersonClickListener) {
            this.onPersonClickListener = onPersonClickListener ;
        }
    
    
        @Override
        public PeopleAdapter.PersonViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            PersonView view = (PersonView) LayoutInflater.from(parent.getContext())
                                        .inflate(R.layout.item_view_person, parent, false) ;
            return new PersonViewHolder(view) ;
        }
    
        @Override
        public void onBindViewHolder(PersonViewHolder holder, int position) {
            holder.personView.setOnPersonClickListener(onPersonClickListener) ;
            holder.personView.setUser(getData().get(position)) ;
        }
    }