如何在 RealmRecyclerViewAdapter 中实现可过滤

Posted

技术标签:

【中文标题】如何在 RealmRecyclerViewAdapter 中实现可过滤【英文标题】:how to implement filterable in RealmRecyclerViewAdapter 【发布时间】:2017-03-30 13:04:10 【问题描述】:

我正在使用 RealmRecyclerViewAdapter。我的问题是实现一个不起作用的Filterable。这是代码:

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

        
    

然后我返回错误:

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

过滤并更新适配器后如何保存结果?

谢谢

【问题讨论】:

【参考方案1】:

将过滤移至publishResults 并使用 UI 线程 Realm 的查询来评估新结果。

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

【讨论】:

很高兴听到我可以简化您使用 Realm 的方式:p @EpicPandaForce - 你能给我看看 updateData(listAirports);如何在过滤器前后更新列表视图项? @user2269164 它是来自github.com/realm/realm-android-adapters的RealmRecyclerViewAdapter方法 @EpicPandaForce - 任何为列表视图实现的代码? @pentarex 复制粘贴错误。甚至不应该在那里。【参考方案2】:

在您的适配器中添加它可能会对您有所帮助

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()

【讨论】:

以上是关于如何在 RealmRecyclerViewAdapter 中实现可过滤的主要内容,如果未能解决你的问题,请参考以下文章

如何在表单提交后保留文本(如何在提交后不删除自身?)

如何在异步任务中调用意图?或者如何在 onPostExecute 中开始新的活动?

在 Avkit 中如何使用这三行代码,以及如何将音乐静音”

如何在 JDBC 中启动事务?

如何在 Fragment 中调用 OnActivityResult 以及它是如何工作的?

如何使用 Firebase 在 Web 上托管 Flutter?它的效果如何?