ste9206 ste9206 - 10 months ago 109
Android Question

how to implement filterable in RealmRecyclerViewAdapter

I'm using well RealmRecyclerViewAdapter. My problem is to implement a

Filterable
that not works. This is the code:

private class AirportAdapter extends RealmRecyclerViewAdapter<AirportR,RecyclerView.ViewHolder> implements Filterable
{
Context context;
OrderedRealmCollection<AirportR>listAirports;

public AirportAdapter(Context activity, OrderedRealmCollection<AirportR>airports)
{
super(activity,airports, true);
this.context = activity;
this.listAirports = airports;
}

@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
{
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.airport_show, parent,false);
AirportClass holder = new AirportClass(view);
return holder;

}

@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position)
{
AirportR airportR = listAirports.get(position);

AirportClass mHolder = (AirportClass)holder;

mHolder.country.setText(airportR.getIsoCountry());
mHolder.name.setText(airportR.getName());
}

public Filter getFilter()
{
AirportFilter filter = new AirportFilter(this, listAirports);
return filter;
}


private class AirportFilter extends Filter
{
private final AirportAdapter adapter;

OrderedRealmCollection<AirportR>originalList;
OrderedRealmCollection<AirportR>filteredList;


private AirportFilter(AirportAdapter adapter, OrderedRealmCollection<AirportR> originalList)
{
super();
this.adapter = adapter;
this.originalList = originalList;

}


@Override
protected FilterResults performFiltering(CharSequence constraint)
{
filteredList.clear();
final FilterResults results = new FilterResults();

if (constraint.length() == 0)
{
filteredList.addAll(originalList);
}
else
{
final String filterPattern = constraint.toString().toLowerCase().trim();

for (final AirportR airportR : originalList)
{
if (airportR.getName().toLowerCase().contains(filterPattern))
{
filteredList.add(airportR);
}
}
}
results.values = filteredList;
results.count = filteredList.size();
return results;
}

@Override
protected void publishResults(CharSequence constraint, FilterResults results)
{
adapter.listAirports.addAll((OrderedRealmCollection<AirportR>) results.values);
adapter.notifyDataSetChanged();
}
}



private class AirportClass extends RecyclerView.ViewHolder
{
TextView name, country;
ImageView image;

public AirportClass(View itemView)
{
super(itemView);

name = (TextView)itemView.findViewById(R.id.name);
country = (TextView)itemView.findViewById(R.id.country);
image = (ImageView)itemView.findViewById(R.id.imageView);

}
}
}


and I give back the error:

java.lang.UnsupportedOperationException: This method is not supported by RealmResults.
at io.realm.RealmResults.addAll(RealmResults.java:710)
at com.example.matteo.downloadairports.fragment.ListAirportFragment$AirportAdapter$AirportFilter.publishResults


how could I save the result after I filter it and update the adapter?

Thanks

Answer Source

Move the filtering to performResults and use the UI thread Realm's queries to evaluate the new results.

private class AirportAdapter
        extends RealmRecyclerViewAdapter<AirportR, RecyclerView.ViewHolder>
        implements Filterable {
    Realm realm;
    Context context;
    OrderedRealmCollection<AirportR> listAirports;

    public AirportAdapter(Realm realm, Context activity, OrderedRealmCollection<AirportR> airports) {
        super(activity, airports, true);
        this.context = activity;
        this.listAirports = airports;
        this.realm = realm;
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.airport_show, parent, false);
        AirportClass holder = new AirportClass(view);
        return holder;
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        AirportR airportR = listAirports.get(position);

        AirportClass mHolder = (AirportClass) holder;

        mHolder.country.setText(airportR.getIsoCountry());
        mHolder.name.setText(airportR.getName());
    }

    public void filterResults(String text) {
        text = text == null ? null : text.toLowerCase().trim();
        if(text == null || "".equals(text)) {
            listAirports = realm.where(AirportR.class).findAll();
        } else {
            listAirports = realm.where(AirportR.class)
                                .contains("fieldToQueryBy", text, Case.INSENSITIVE) // TODO: change field
                                .findAll(); 
        }
        updateData(listAirports);
    }

    public Filter getFilter() {
        AirportFilter filter = new AirportFilter(this);
        return filter;
    }

    private class AirportFilter
            extends Filter {
        private final AirportAdapter adapter;

        private AirportFilter(AirportAdapter adapter) {
            super();
            this.adapter = adapter;
        }

        @Override
        protected FilterResults performFiltering(CharSequence constraint) {
            return new FilterResults();
        }

        @Override
        protected void publishResults(CharSequence constraint, FilterResults results) {
            adapter.filterResults(constraint.toString());
        }
    }

    private class AirportClass
            extends RecyclerView.ViewHolder {
        TextView name, country;
        ImageView image;

        public AirportClass(View itemView) {
            super(itemView);

            name = (TextView) itemView.findViewById(R.id.name);
            country = (TextView) itemView.findViewById(R.id.country);
            image = (ImageView) itemView.findViewById(R.id.imageView);
        }
    }
}