在RecyclerView中过滤需要很长时间

时间:2015-04-23 00:41:19

标签: android android-recyclerview listadapter android-filter android-filterable

我正在使用一组约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 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);
    }

1 个答案:

答案 0 :(得分:0)

分裂(&#34; \ s +&#34;)是罪魁祸首,因为它每次都会为正则表达式评估创建一个模式。由于所需要的只是基于空格的简单拆分,因此我使用了Apache commons split方法。这样可以实现基本的分割,速度更快,并且可以将时间缩短一半。