在 RecyclerView 中过滤需要很长时间

Filtering in RecyclerView takes long

我正在测试一组大约 5000 个对象。我使用自定义比较器 (MyOwnSort) 根据业务逻辑对值进行排序。

    public Filter getFilter() {
    if (_filter == null) {
        _filter = new Filter() {

            @Override
            protected FilterResults performFiltering(CharSequence constraint) {
                String charText = constraint.toString();
                FilterResults filterResults = new FilterResults();

                // Clear the data
                visibleData.clear();
                for (String title : data) {
                    if (title.startsWith(charText)) {
                        visibleData.add(title);
                    }

                }

                myOwnSort.setSearchString(charText);
                Collections.sort(visibleData, myOwnSort);
            }

            filterResults.count=visibleData.size();
            filterResults.values=visibleData;

            return filterResults;
        }

        @Override
        protected void publishResults (CharSequence constraint, FilterResults results){

            notifyDataSetChanged();
        }
    } ;
}

return _filter;

}

这需要 200 到 1600 毫秒之间的某个时间,具体取决于 android 设备。当我开始键入以过滤数据时,这会花费特别长的时间,因为过滤的数据很大。随着您继续输入更多内容,数据集会缩小并且速度会更快。如您所见,performFiltering 在后台线程中 运行,因此它不会阻塞 ui 线程。然而,结果不会立即显示出来,所以它看起来并不活泼。这是正常的吗?我可以做些什么来改善这一点吗?如果不是,我怎样才能让体验更好? 编辑:添加了 CustomComparator class.

class CustomComparator implements Comparator<String> {
    private String _searchString;

    public CustomSearchStringComparator(String searchString) {
        _searchString = searchString;
    }

    public void setSearchString(String searchString) {
        _searchString = searchString;
    }

    @Override
    public int compare(String lhs, String rhs) {
int res = customCompare(lhs, rhs);

        // finally alphabetic
        if (res == 0) {
            res = alphaCompare(lhs, rhs);
        }

        return res;
    }

    private int customCompare(String lhs, String rhs) {
            String lhsTitle = lhs.toLowerCase(Locale.getDefault());
            String rhsTitle = rhs.toLowerCase(Locale.getDefault());

            String[] lhsNames = lhsTitle.split("\s+");
            String lhsFirstName = lhsNames[0];
            String lhsLastName = lhsNames.length > 1 ? lhsNames[1] : "";

            // if there is a middle name...
            if (lhsNames.length > 2) {
                lhsLastName = lhsNames[2];
            }

            String[] rhsNames = rhsTitle.split("\s+");
            String rhsFirstName = rhsNames[0];
            String rhsLastName = rhsNames.length > 1 ? rhsNames[1] : "";

            // if there is a middle name...
            if (rhsNames.length > 2) {
                rhsLastName = rhsNames[2];
            }

            boolean lhsFirstNameContains = lhsFirstName.startsWith(_searchString);
            boolean rhsFirstNameContains = rhsFirstName.startsWith(_searchString);
            boolean lhsLastNameContains = lhsLastName.startsWith(_searchString);
            boolean rhsLastNameContains = rhsLastName.startsWith(_searchString);

            if (lhsFirstNameContains == rhsFirstNameContains) {
                if (lhsLastNameContains == rhsLastNameContains) {
                    return 0;
                } else {
                    return rhsLastNameContains ? 1 : -1;
                }
            } else {
                return rhsFirstNameContains ? 1 : -1;
            }
    }

   private int alphaCompare(String lhs, String rhs) {
        return String.CASE_INSENSITIVE_ORDER.compare(lhs, rhs);
    }

split("\s+") 是罪魁祸首,因为它每次都在为正则表达式评估创建一个模式。由于所需要的只是基于空格的简单拆分,因此我使用了 Apache commons 拆分方法。这会进行基本拆分,而且速度更快,并且大大减少了一半的时间。