ste9206 ste9206 - 19 days ago 8
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

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);
        }
    }
}
Comments