how to implement filterable in RealmRecyclerViewAdapter
Asked Answered
A

2

7

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

Arbutus answered 16/11, 2016 at 10:54 Comment(0)
M
10

Move the filtering to publishResults 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;

    public AirportAdapter(Context context, Realm realm, OrderedRealmCollection<AirportR> airports) {
        super(context, airports, true);
        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 = getData().get(position);

        AirportClass mHolder = (AirportClass) holder;
        mHolder.bind(airportR);
    }

    public void filterResults(String text) {
        text = text == null ? null : text.toLowerCase().trim();
        RealmQuery<AirportR> query = realm.where(AirportR.class);
        if(!(text == null || "".equals(text))) {
            query.contains("fieldToQueryBy", text, Case.INSENSITIVE) // TODO: change field
        }
        updateData(query.findAllAsync());
    }

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

        public void bind(AirportR airportR) {            
            country.setText(airportR.getIsoCountry());
            name.setText(airportR.getName());
        }
    }
}
Muzzle answered 16/11, 2016 at 12:50 Comment(9)
Glad to hear I could simplify how you use Realm :pMuzzle
@Muzzle - Could you show me the updateData(listAirports); how can i update the listview items after and before filter?Inventive
@Inventive it is a method of RealmRecyclerViewAdapter from github.com/realm/realm-android-adaptersMuzzle
@Muzzle - Any code which is implemented for listview?Inventive
Same thing just use RealmBaseAdapterMuzzle
where is listAirports coming from or its a copy/paste error and should be airports instead?Ubiquitarian
@pentarex copy-paste error. Shouldn't even be there.Muzzle
@Muzzle is it ok to trigger that realm query on the UI thread?Kweilin
Depends on your datasize set, though you are right, as RealmRecyclerViewAdapter is used, you can use findAllAsync insteadMuzzle
O
1

in your adapter add this it may help you

fun filterResults(text: String?, realm: Realm) {
    var text = text
    text = text?.toLowerCase()?.trim { it <= ' ' }
    val query = realm.where(YourObject::class.java)
    if (!(text == null || "" == text)) {
        query.contains("username", text, Case.INSENSITIVE).or().contains("username2", text, Case.INSENSITIVE)
    }
    updateData(query.findAllAsync()) // or findAll()
}
Oxime answered 23/1, 2019 at 12:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.