Android listview中的筛选器未从完整列表中筛选,而是从已筛选的列表中筛选

Android listview中的筛选器未从完整列表中筛选,而是从已筛选的列表中筛选,android,android-listview,android-filter,Android,Android Listview,Android Filter,我有一个带过滤器的列表视图。当我在我用作过滤器的edittext中输入一些单词时,例如“david”,它工作正常,列表中的项目被过滤,它将显示包含“david”的所有项目。但当我删除一些单词时,例如“dav”,列表仍然被过滤,但它是从上一个被“dav”过滤的单词中过滤出来的 假设我有40个项目,通过“david”过滤,它变成24个项目。然后我用“dav”再次过滤,它是从“24项”过滤出来的,而不是从“40项”过滤出来的 这是我的自定义适配器: public class WRegistrantLi

我有一个带过滤器的列表视图。当我在我用作过滤器的edittext中输入一些单词时,例如“david”,它工作正常,列表中的项目被过滤,它将显示包含“david”的所有项目。但当我删除一些单词时,例如“dav”,列表仍然被过滤,但它是从上一个被“dav”过滤的单词中过滤出来的

假设我有40个项目,通过“david”过滤,它变成24个项目。然后我用“dav”再次过滤,它是从“24项”过滤出来的,而不是从“40项”过滤出来的

这是我的自定义适配器:

public class WRegistrantListAdapter extends ArrayAdapter<Registrant> {

    private Context mContext;
    private int mResource;
    private List<Registrant> mOriginalList;
    private List<Registrant> mFilteredList;

    public WRegistrantListAdapter(Context context, int resource, ArrayList<Registrant> oobjects, int workshopItemId) {
        super(context, resource, oobjects);
        mContext = context;
        mResource = resource;
        mFilteredList = oobjects;
    }

    @NonNull
    @Override
    public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
        //contains code for displaying item.
    }

    @NonNull
    @Override
    public Filter getFilter() {
        return new Filter() {

            @Override
            protected FilterResults performFiltering(CharSequence charSequence) {
                FilterResults result = new FilterResults();
                String constraint = charSequence.toString().toLowerCase();

                if (mOriginalList == null) {
                    mOriginalList = mFilteredList;
                    Toast.makeText(mContext, String.valueOf(mOriginalList.size()), Toast.LENGTH_SHORT).show();
                }

                if (constraint == null || constraint.isEmpty() || constraint.equals("")) {
                    result.values = mOriginalList;
                    result.count = mOriginalList.size();
                } else {
                    List<Registrant> list = new ArrayList<>();
                    int max = mOriginalList.size();
                    for (int cont = 0; cont < max; cont++) {
                        Registrant item = mOriginalList.get(cont);
                        boolean contains =
                            item.getRegistrantName().toLowerCase().contains(constraint) ||
                                    item.getRegistrantNumber().toLowerCase().contains(constraint);
                        if (contains) {
                            list.add(mOriginalList.get(cont));
                        }
                    }
                    result.values = list;
                    result.count = list.size();
                }

                return result;
            }

            @Override
            protected void publishResults(CharSequence constraint, FilterResults results) {
                clear();
                addAll((ArrayList<Registrant>) results.values);
                notifyDataSetChanged();
            }
        };
    }
}
公共类WRegistrantListAdapter扩展了ArrayAdapter{
私有上下文;
私人国际资源;
私人名单莫里金主义者;
私人名单;
公共WRegistrantListAdapter(上下文上下文、int资源、ArrayList对象、int workshopItemId){
超级(上下文、资源、对象);
mContext=上下文;
mResource=资源;
mFilteredList=oobjects;
}
@非空
@凌驾
公共视图getView(int位置,@Nullable视图convertView,@NonNull视图组父级){
//包含用于显示项目的代码。
}
@非空
@凌驾
公共过滤器getFilter(){
返回新筛选器(){
@凌驾
受保护过滤器结果执行过滤(CharSequence CharSequence){
FilterResults结果=新的FilterResults();
字符串约束=charSequence.toString().toLowerCase();
if(mOriginalList==null){
mOriginalList=mFilteredList;
Toast.makeText(mContext,String.valueOf(mOriginalList.size()),Toast.LENGTH_SHORT.show();
}
if(constraint==null | | constraint.isEmpty()| | constraint.equals(“”){
result.values=mOriginalList;
result.count=mOriginalList.size();
}否则{
列表=新的ArrayList();
int max=mOriginalList.size();
对于(int cont=0;cont

过滤的哪一部分是错误的?任何帮助都将不胜感激。希望我的解释不会让人困惑,因为英语不是我的母语。

您应该在适配器中保留两个单独的列表,例如

private List<Registrant> mOriginalList = new ArrayList();
private List<Registrant> mFilteredList = new ArrayList();

public WRegistrantListAdapter(Context context, int resource, ArrayList<Registrant> oobjects, int workshopItemId) {
    super(context, resource, oobjects);
    mContext = context;
    mResource = resource;
    mFilteredList.addAll(oobjects);
    mOriginalList.addAll(oobjects);
}
private List mOriginalList=new ArrayList();
私有列表mFilteredList=newarraylist();
公共WRegistrantListAdapter(上下文上下文、int资源、ArrayList对象、int workshopItemId){
超级(上下文、资源、对象);
mContext=上下文;
mResource=资源;
mFilteredList.addAll(对象);
mOriginalList.addAll(对象);
}
最初,它们应该具有相同的值,您将使用filteredList显示数据。在过滤器的后面,您应该发布数据,如

@Override
            protected void publishResults(CharSequence constraint, FilterResults results) {
                filteredList.clear();
                filteredList.addAll((ArrayList<Registrant>) results.values);
                notifyDataSetChanged();
            }
@覆盖
受保护的void publishResults(CharSequence约束、FilterResults结果){
filteredList.clear();
filteredList.addAll((ArrayList)results.values);
notifyDataSetChanged();
}

一个完整的例子是可以在

中找到,您需要两个不同的列表进行筛选,因此请尝试更改mOriginalList=mFilteredList
to
mOriginalList=newarraylist(mFilteredList)可以解决此问题

说明:

mOriginalList=mFilteredList是具有两个不同名称的相同列表。它在模块化程序中很有用,就像
mFilteredList=oobjects在适配器构造函数中

mOriginalList=newarraylist(mFilteredList)
是制作mFilteredList的浅层副本并将其存储为mOriginalList,因此列表不同

浅拷贝和深拷贝:

示例:如果您的自定义类,registent包含名为
sample
的公共字段(列表、地图或自定义对象等,需要创建new)。在浅拷贝下,
mOriginalList=newarraylist(mFilteredList),mOriginalList.get(i)是mFilteredList.get(i)的副本,它们是两个不同的注册者对象。但是mOriginalList.get(i).sample和mFilteredList.get(i).sample是同一个对象

如果需要将mOriginalList.get(i).sample和mFilteredList.get(i).sample作为不同的对象,则称为深度复制。没有现成的方法进行深度复制,您必须根据自定义类创建自己的方法。但到目前为止,我还没有一个案例需要深度复制


希望有帮助

我试过你的建议,但结果还是一样。mList的大小已更改,但我没有对其执行任何操作。我根据您提供的链接更新了代码库。我将mList更改为mOriginalList,以使其更易于理解。但仍然是一样的,mOriginalList的大小发生了变化,因为它不应该将相同的对象分配给两个列表。您可以在构造函数中执行此操作。我已经更新了我的答案,希望