带有分组标题的列表视图

3
我看过很多关于如何在列表视图中添加字母索引标题的例子。例如:

section headers

我实现了来自这个网站的功能。然而,我有大约8000个项目的列表。尝试加载此页面需要约8秒钟,这显然太慢了。仅使用普通的AlphabetIndexer需要大约1.5秒(仍然很慢,但好得多)。
有人有任何加速此过程的想法吗?如果没有,是否有比这更快的其他示例?
谢谢!

看一下这个链接:http://developer.android.com/resources/tutorials/views/hello-listview.html,虽然它不能像你想要的那样快速滚动字母,但它似乎更轻便,加载速度也很快。 - FabianCook
1.5秒处理8000个项目,你认为这很慢吗? - Squonk
@SmartLemon 谢谢,但是快速滚动对于这个列表来说非常重要。 - Nick
@MisterSquonk 它永远不够快 :) - Nick
2个回答

1
尝试加载页面到底是指什么?如果只加载项目而不进行任何索引,需要多长时间?8000个项目并不多。但是从磁盘或互联网加载的项目可能非常多。您可能要考虑显示加载屏幕并在后台读取行数据。
您展示的代码对于您尝试做的事情来说似乎特别复杂。以下是我使用过的解决方案。您可以搜索SectionIndexer。在我的代码中,itemManager基本上只是列表的抽象,占位符是空值,其他所有内容都是包含行信息的数据结构。有些代码被省略了:
//based on http://twistbyte.com/tutorial/android-listview-with-fast-scroll-and-section-index

private class ContactListAdapter extends BaseAdapter implements SectionIndexer {
    final HashMap<String, Integer> alphaIndexer = new HashMap<String, Integer>();
    final HashMap<Integer, String> positionIndexer = new HashMap<Integer, String>();
    String[] sections;

    public ContactListAdapter() {
        setupHeaders();
    }

    public void setupHeaders(){
        itemManager.clearPlaceholders();
        for (int i = 0; i < itemManager.size(); i++) {
            String name = itemManager.get(i).displayName();
            String firstLetter = name.substring(0, 1);
            if (!alphaIndexer.containsKey(firstLetter)) {
                itemManager.putPlaceholder(i);
                alphaIndexer.put(firstLetter, i);
                positionIndexer.put(i, firstLetter);
                ++i;
            }

        }
        final Set<String> sectionLetters = alphaIndexer.keySet();
        final ArrayList<String> sectionList = new ArrayList<String>(sectionLetters);
        Collections.sort(sectionList);
        sections = new String[sectionList.size()];
        sectionList.toArray(sections);
    }

    @Override
    public int getItemViewType(int position) {
        return itemManager.isPlaceholder(position) ? ViewType.HEADER.ordinal() : ViewType.CONTACT.ordinal();
    }

    @Override
    public int getViewTypeCount() {
        return ViewType.values().length;
    }

    @Override
    public int getPositionForSection(int section) {
        return alphaIndexer.get(sections[section]);
    }

    @Override
    public int getSectionForPosition(int position) {
        return 1;
    }

    @Override
    public Object[] getSections() {
        return sections;
    }

我不能填写,但你不应该有太多麻烦。你有什么特别困难的地方吗? - Sam Judd
我对itemManager.putPlaceholder(i)感到困惑。itemManager本身是由什么派生而来的?另外,在getSectionForPosition中,你只返回1。无论如何,感谢您的回复。 - user468311
getSectionForPosition 不执行任何操作,所以您可以返回任何您想要的内容。itemManager 是一个不重要的抽象概念。只需将 itemManager 视为列表,并将 putPlaceholder 视为在特定位置插入 null。isPlaceholder 可以表示为 list.get(index) == null。还请注意,我的原始代码并不理想(在迭代列表时不应修改列表),但是一旦您掌握了这个思路,修复它就不难了。 - Sam Judd

0

ListView适配器有一个你可以重写的类叫做getViewType(int position)getViewTypeCount()

你需要重写这些函数来让Android知道你的适配器使用了多少种不同类型的视图。

在你的情况下,重写getViewTypeCount()返回2,因为你将有两种类型的视图。一种是标准视图,另一种是头部视图。

接下来,你需要知道何时显示头部视图。一旦确定了位置,你就可以轻松地在getView(...)函数中返回你的视图。


那就是我提供的链接所做的事情。但是,我认为导致速度变慢的是“知道您将在哪个位置显示标题视图”的部分。这就是我想要加快速度的部分,但我不确定从哪里开始。 - Nick
我建议你将数据缓存到SQLite数据库中。在那里,你可以轻松快速地排序和添加这些标题行。然后将该数据库数据放入适配器中将变得非常快速和容易! - Jona

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接