java - 清除搜索后 ListView 未返回原始状态

标签 java android xml android-activity android-listfragment

每当我从搜索 View 中取消搜索时,我都会尝试让我的列表再次显示所有项目,但由于某种奇怪的原因,该列表仅显示上一次搜索的结果。有谁知道我的代码有什么问题以及如何解决这个问题?我相信与过滤器相关的代码有问题,但我不知道它是什么。

FilterListFragment.java

public class ItemListAdapter extends BaseAdapter implements Filterable {

    private List<Item> mData;
    private List<Item> mFilteredData;
    private LayoutInflater mInflater;
    private ItemFilter mFilter;

    public ItemListAdapter (List<Item> data, Context context) {
        mData = data;
        mFilteredData = data;
        mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }

    @Override
    public int getCount() {
        return mFilteredData.size();
    }

    @Override
    public String getItem(int position) {
        return mFilteredData.get(position).getItem();
    }

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

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        ViewHolder holder;
        if (convertView == null) {
           convertView = mInflater.inflate(R.layout.item_row, parent, false);
            holder = new ViewHolder();

            holder.title = (TextView) convertView.findViewById(R.id.item_title);
            holder.description = (TextView) convertView.findViewById(R.id.item_description);

            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }

        holder.title.setText(mData.get(position).getItem());
        holder.description.setText(mData.get(position).getItemDescription());

        return convertView;
    }

    @Override
    public Filter getFilter() {
        if (mFilter == null) {
            mFilter = new ItemFilter();
        }
        return mFilter;
    }

    /**
     * View holder
     */
    static class ViewHolder {
        private TextView title;
        private TextView description;
    }

    /**
     * Filter for filtering list items
     */
    private class ItemFilter extends Filter {

        /**
         * Invoked on a background thread.  This is where all the filter logic should go
         * @param constraint the constraint to filter on
         * @return the resulting list after applying the constraint
         */
        @Override
        protected FilterResults performFiltering(CharSequence constraint) {
            FilterResults results = new FilterResults();

            if (TextUtils.isEmpty(constraint)) {
                results.count = mData.size();
                results.values = mData;
            } else {
                //Create a new list to filter on
                List<Item> resultList = new ArrayList<Item>();
                for (Item str : mData) {
                    if (str.getItem().toLowerCase().contains(constraint.toString().toLowerCase())) {
                        resultList.add(str);
                    }
                }
                results.count = resultList.size();
                results.values = resultList;
            }
            return results;
        }

        /**
         * Runs on ui thread
         * @param constraint the constraint used for the result
         * @param results the results to display
         */
        @SuppressWarnings("unchecked")
        @Override
        protected void publishResults(CharSequence constraint, FilterResults results) {

            if (results.count == 0) {
                notifyDataSetInvalidated();
            } else {
                mFilteredData = (ArrayList<Item>)results.values;
                notifyDataSetChanged();
            }
        }
    }
}

正常状态下的列表 enter image description here

处于过滤状态的列表 enter image description here

最佳答案

您正在操作原始数据而不是过滤后的数据。您应该保留对原始数据的引用,并将过滤后的数据用于所有其他目的。以便清除搜索时显示原始数据。

mData的所有用法替换为mFilteredData,如下所示,仅使用原始数据来生成过滤后的数据:

private List<String> mData;
private List<String> mFilteredData;
private LayoutInflater mInflater;
private ItemFilter mFilter;

public ItemListAdapter (List<String> data, Context context) {
    mData = data;
    mFilteredData = data;
    mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}

@Override
public int getCount() {
    return mFilteredData.size();
}

@Override
public String getItem(int position) {
    return mFilteredData.get(position);
}

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

@Override
public View getView(int position, View convertView, ViewGroup parent) {

    String strItem = mFilteredData.get(position);
    ViewHolder holder;
    if (convertView == null) {
       convertView = mInflater.inflate(R.layout.item_row, parent, false);

        holder = new ViewHolder();
        holder.mTvItem = (TextView) convertView.findViewById(R.id.tv_item);
        convertView.setTag(holder);
    } else {
        holder = (ViewHolder) convertView.getTag();
    }

    holder.mTvItem.setText(strItem);

    return convertView;
}

@Override
public Filter getFilter() {
    if (mFilter == null) {
        mFilter = new ItemFilter();
    }
    return mFilter;
}

/**
 * View holder
 */
static class ViewHolder {
    private TextView mTvItem;
}

/**
 * Filter for filtering list items
 */
private class ItemFilter extends Filter {

    /**
     * Invoked on a background thread.  This is where all the filter logic should go
     * @param constraint the constraint to filter on
     * @return the resulting list after applying the constraint
     */
    @Override
    protected FilterResults performFiltering(CharSequence constraint) {

        FilterResults results = new FilterResults();

        if (TextUtils.isEmpty(constraint)) {
            results.count = mData.size();
            results.values = mData;
        } else {
            //Create a new list to filter on
            List<String> resultList = new ArrayList<>();
            for (String str : mData) {
                if (str.toLowerCase().contains(constraint.toString().toLowerCase())) {
                    resultList.add(str);
                }
            }
            results.count = resultList.size();
            results.values = resultList;
        }
        return results;
    }

    /**
     * Runs on ui thread
     * @param constraint the constraint used for the result
     * @param results the results to display
     */
    @SuppressWarnings("unchecked")
    @Override
    protected void publishResults(CharSequence constraint, FilterResults results) {

        if (results.count == 0) {
            notifyDataSetInvalidated();
        } else {
            mFilteredData = (ArrayList<String>)results.values;
            notifyDataSetChanged();
        }
    }
}

关于java - 清除搜索后 ListView 未返回原始状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30985218/

相关文章:

android - 我可以添加一个按钮吗?

C# 查询 XML 文档

Java流: Nested Stream lookup Over Multiple List throws NPE

android - 找不到 Gradle DSL 方法 : 'resValue()' error

Eclipse 上的 Android AVD 显示 'Blank Screen' 没有 Activity

c# - C# 中 (ResourceWriter & ResXResourceWriter) 和 (ResourceReader & ResXResourceReader) 之间的区别

Java:如何编写 `zip` 函数?返回类型应该是什么?

java - 每个请求一个新的 HttpSession?

java - 是否可以在不编辑 java.policy 文件的情况下运行 Java Applet?

android - 管理来自不同 rx.Observables 的不同异常