首页 > 解决方案 > 在回收站视图中过滤结果为 0 时显示空状态

问题描述

我得到了searchView我用来过滤recyclerView的这个。因此,当某些搜索查询没有结果时,我想textView通过将其可见性设置为VISIBLE. 所以在 searchView 监听器中,我这样做:

            @Override
            public boolean onQueryTextChange(String s) {
                adapter.getFilter().filter(s);

                if (adapter.getItemCount()<=0){
                    emptyStateConatiner.setVisibility(View.VISIBLE);
                }
                else  emptyStateConatiner.setVisibility(View.GONE);

                return false;
            }

但这并不像我期望的那样工作,因为当我输入不存在的搜索查询时,它首先显示为空recyclerView,然后只有在此之后,如果我在该查询中输入额外的字母,我就会得到emptyStateContainer显示。

有谁知道是什么导致了这种行为?

这是适配器代码:package com.app.userprofile;

import android.content.res.Resources;
import android.support.annotation.NonNull;
import android.support.v7.widget.CardView;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.Filter;
import android.widget.Filterable;

import com.app.R;
import com.app.data.webservice.collection_response.Datum;

import java.util.ArrayList;
import java.util.List;

public class BasicUserProfileInfoListAdapter extends RecyclerView.Adapter<BasicUserProfileInfoListAdapter.BasicInfoViewHolder> implements Filterable {

    private List<Datum> offeredChoices = new ArrayList<>();
    private List<Datum> offeredChoicesFiltered = new ArrayList<>();
    private List<Datum> previouslySelectedChoices = new ArrayList<>();


    private Resources resources;
    private ItemClickCallback clickCallback;

    //for single choices
    int mCheckedPostion=-1;

    public BasicUserProfileInfoListAdapter(ItemClickCallback clickCallback){
        this.clickCallback = clickCallback;
    }

    public void setList(List<Datum> datumList) {
        this.offeredChoices = datumList;
        this.offeredChoicesFiltered = datumList;
        notifyDataSetChanged();
    }






    @NonNull
    @Override
    public BasicInfoViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
        View itemView = LayoutInflater.from(viewGroup.getContext())
                .inflate(R.layout.basic_choice_item, viewGroup, false);
        if (resources == null) {
            resources = itemView.getContext().getApplicationContext().getResources();
        }

        return new BasicInfoViewHolder(itemView);
    }

    @Override
    public void onBindViewHolder(@NonNull final BasicInfoViewHolder basicInfoViewHolder, final int i) {
        final Datum currentData = offeredChoicesFiltered.get(i);

        basicInfoViewHolder.basicInfoCheckBox.setText(currentData.getDesc());
        //TODO if currentData equals some choice in previouslySelectedChoices, than mark it checked and add it to selected choices via interface

       if (clickCallback instanceof MultipleChoiceItemClickCallback && previouslySelectedChoices!=null && !previouslySelectedChoices.isEmpty()){
           boolean shouldCheck=false;
           for (Datum data:previouslySelectedChoices) {
               if ((data.getId().equals(currentData.getId()))/*&& data.getDesc().equals(currentData.getDesc())*/){
                   shouldCheck=true;
                   clickCallback.onRowClicked(currentData,ChoiceClickType.ADD_CHOICE);
               }
           }
           basicInfoViewHolder.basicInfoCheckBox.setChecked(shouldCheck);
       }

        if (clickCallback instanceof SingleChoiceItemClickCallback){
            basicInfoViewHolder.basicInfoCheckBox.setChecked(i == mCheckedPostion);
            if (previouslySelectedChoices!=null && !previouslySelectedChoices.isEmpty()){
                boolean shouldCheck=false;
                for (Datum data:previouslySelectedChoices) {
                    if ((data.getId().equals(currentData.getId()))/*&& data.getDesc().equals(currentData.getDesc())*/){
                        shouldCheck=true;
                        previouslySelectedChoices.clear();//so it wouldn't reselect on notifyDataSetChanged()
                        clickCallback.onRowClicked(currentData,ChoiceClickType.ADD_SINGLE_CHOICE);
                    }

                }

                if (shouldCheck) mCheckedPostion = i;
                //Log.d("slctdwf","choice: "+ currentData.getDesc()+", position: "+mCheckedPostion);
                basicInfoViewHolder.basicInfoCheckBox.setChecked(shouldCheck);
            }


        }
    }

    @Override
    public int getItemCount() {
        if (offeredChoicesFiltered!=null) return offeredChoicesFiltered.size();
        else  return 0;
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public int getItemViewType(int position) {
        return position;
    }

    private Datum getCurrentRowInfo(int position) {
        return offeredChoicesFiltered.get(position);
    }

    public void setPreviouslySelectedChoices (List<Datum> data) {
        if (data!=null && !data.isEmpty()){
        this.previouslySelectedChoices = data;
        notifyDataSetChanged();
        }
    }

    @Override
    public Filter getFilter() {
        return new Filter() {
            @Override
            protected FilterResults performFiltering(CharSequence constraint) {
                String charString = constraint.toString();
                List<Datum> filteredList = new ArrayList<>();
                if (charString.isEmpty()) {
                    filteredList = offeredChoices;
                } else {
                    for (Datum choice : offeredChoices) {

                        if (choice.getDesc().toLowerCase().contains(charString.toLowerCase())) {
                            filteredList.add(choice);
                        }
                    }

                }

                FilterResults filterResults = new FilterResults();
                filterResults.count = filteredList.size();
                filterResults.values = filteredList;
                return filterResults;
            }

            @Override
            protected void publishResults(CharSequence constraint, FilterResults results) {
                offeredChoicesFiltered = (ArrayList<Datum>) results.values;
                notifyDataSetChanged();
            }
        };
    }

    class BasicInfoViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
        private CheckBox basicInfoCheckBox;
        private CardView entireRowCardView;

        BasicInfoViewHolder(View itemView) {
            super(itemView);
            basicInfoCheckBox = itemView.findViewById(R.id.choice_checkbox);
            entireRowCardView = itemView.findViewById(R.id.entire_row_basic_choice);
            entireRowCardView.setOnClickListener(this);
            if (resources == null) {
                resources = itemView.getResources();
            }

        }

        @Override
        public void onClick(View v) {
            Datum currentChoice = getCurrentRowInfo(getAdapterPosition());
            int position = getAdapterPosition();

            if (clickCallback instanceof MultipleChoiceItemClickCallback){
                if (basicInfoCheckBox.isChecked()){
                    basicInfoCheckBox.setChecked(false);
                    clickCallback.onRowClicked(currentChoice, ChoiceClickType.REMOVE_CHOICE);
                }
                else if (!basicInfoCheckBox.isChecked()){
                    basicInfoCheckBox.setChecked(true);
                    clickCallback.onRowClicked(currentChoice, ChoiceClickType.ADD_CHOICE);
                }
            }

            if (clickCallback instanceof SingleChoiceItemClickCallback){
                        if (position == mCheckedPostion) {
                            mCheckedPostion = -1;
                            //Log.d("slctdwf","removed single choice: "+ currentChoice.getDesc());
                            clickCallback.onRowClicked(currentChoice, ChoiceClickType.REMOVE_SINGLE_CHOICE);
                            basicInfoCheckBox.setChecked(false);
                            notifyDataSetChanged();

                        } else {
                            mCheckedPostion = position;
                            //Log.d("slctdwf","added single choice: "+ currentChoice.getDesc());
                            clickCallback.onRowClicked(currentChoice, ChoiceClickType.ADD_SINGLE_CHOICE);
                            basicInfoCheckBox.setChecked(true);
                            notifyDataSetChanged();
                        }


            }

        }
    }



    public interface ItemClickCallback {
        void onRowClicked(Datum choiceData, ChoiceClickType choiceClickType);
    }

    public interface MultipleChoiceItemClickCallback extends ItemClickCallback{
        void onRowClicked(Datum choiceData, ChoiceClickType choiceClickType);
    }

    public interface SingleChoiceItemClickCallback extends ItemClickCallback {
        void onRowClicked(Datum choiceData, ChoiceClickType choiceClickType);
    }

    public enum ChoiceClickType {
        ADD_CHOICE,
        REMOVE_CHOICE,
        ADD_SINGLE_CHOICE,
        REMOVE_SINGLE_CHOICE
    }

}

标签: androidandroid-recyclerview

解决方案


我认为 onQueryChanged 回调是控制空状态的错误位置。您可以使用DataSetObserver (文档)来收听列表更改,因此您始终拥有正确的 size() 匹配项。

注册一个观察者,当此适配器使用的数据发生更改时调用该观察者。

adapter.registerDataSetObserver(new DataSetObserver() {
    @Override public void onChanged() {
        super.onChanged();
        showEmptyStateIfAdapterIsEmpty();
        // access adapter's dataset size here or in that method
    } 
});

推荐阅读