【问题标题】:List View with Section Headings带有部分标题的列表视图
【发布时间】:2012-03-02 12:34:36
【问题描述】:

我已经看到了很多如何将按字母顺序排列的部分标题添加到在线列表视图的示例。示例:

我从 this website .但是,我有一个大约 8000 项的列表。尝试加载此页面时大约需要 8 秒,这显然太慢了。仅使用普通的 AlphabetIndexer 大约需要 1.5 秒(仍然很慢,但要好得多)。

有人对如何加快速度有任何想法吗?如果没有,还有其他比这更快的例子吗?

谢谢!

【问题讨论】:

  • 看看这个,developer.android.com/resources/tutorials/views/…,我知道它不是你想要的,因为你不能使用快速滚动字母,但它似乎更轻,而且加载速度很快
  • 8000 个项目需要 1.5 秒,您认为这很慢吗?
  • @SmartLemon 谢谢,但快速滚动对于此列表非常重要。
  • @MisterSquonk 它永远不够快:)

标签: android listview optimization


【解决方案1】:

尝试加载页面到底是什么意思?如果只加载项目而不做任何索引,需要多长时间? 8000 个项目并没有太多需要迭代。但是,可能需要从磁盘或 Internet 加载很多项目。您可能需要考虑显示加载屏幕并在后台读取行的数据。

您显示的代码对于您要执行的操作而言看起来特别复杂。以下是我使用过的解决方案。您可以谷歌搜索 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;
    }

【讨论】:

  • 我不能,但你不应该有太多麻烦来填写我遗漏的任何内容。你有什么特别的问题吗?
  • 我对 itemManager.putPlaceholder(i) 感到困惑; itemManager 本身是从什么衍生而来的?同样在 getSectionForPosition 中,您只需返回 1。无论如何,感谢您的回复。
  • getSectionForPosition 不执行任何操作,因此您可以返回任何您想要的内容。 itemManager 是一个无关紧要的抽象。只需将 itemManager 视为一个列表,将 putPlaceholder 视为在特定位置插入 null 即可。 isPlaceholder 可以是 list.get(index) == null。另请注意,我的原始代码不太理想(不应该在迭代列表时修改列表),但是一旦你明白了它就不难修复。
【解决方案2】:

ListView 适配器有一个可以覆盖的类,称为 getViewType(int position)getViewTypeCount()

您将覆盖这些内容以允许 Android 知道您的适配器使用了多少种不同类型的视图。

在您的情况下,覆盖 getViewTypeCount() 以返回 2,因为您将拥有两种类型的视图。一个是标准视图,第二个是标题视图。

您需要知道在什么位置显示标题视图。完成后,您可以轻松地返回您对 getView(...) 函数的看法。

【讨论】:

  • 这就是我提供的链接的作用。但是,我认为这是“知道您将在什么位置显示标题视图”这会减慢速度。这就是我正在研究如何加快速度的部分,但我不确定从哪里开始。
  • 我建议您将数据缓存在 SQLite 数据库中。在那里,您可以轻松快速地排序并添加这些标题行。比将数据库数据放入适配器将超级快速和容易!
猜你喜欢
  • 2019-09-20
  • 1970-01-01
  • 2017-05-15
  • 1970-01-01
  • 1970-01-01
  • 2014-08-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多