android - ListView/CursorAdapter 动态生成列表标题

标签 android performance android-listview android-sqlite

我有一个这样的数据库表:

ID
NAME
COUNTRY_NAME

我想要这样的列表:

+ Italy
    - Potato
    - Tomato
+ France
    - Fromage
    - Baguette

我写了一个 CursorAdapter,每次调用重新查询时,读取表中的所有项目并将其映射到一个对象中,该对象用于映射每个项目(实际项目或标题)的位置。

private  static class PersonEntry {
    boolean isHeader;
    String countryName;
    int realPos;
    int id;
}

代码是这样的:

 /* cursor generated by querying whole table */

 public void readHeaders(Cursor cursor ) {
    Log.d(this.getClass().getSimpleName(),"readHeaders init");
    items = new ArrayList<PersonEntry >();
    this.mCursor = cursor;

    cursor.moveToFirst();
    int i = 0;
    String previousCountry = "";
    String currentCountry;
    while(cursor.isAfterLast() == false)  {
        int id = cursor.getInt(cursor.getColumnIndexOrThrow(Match.ROW_ID));
        currentCountry = cursor.getString(cursor.getColumnIndexOrThrow(Person.ROW_COUNTRY_NAME));
        if (!currentCountry.equals(previousCountry)) {
            // ho incontrato una nuova nazione
            // rispetto alla precedente, aggiungiamola
            items.add(new PersonEntry(... define isHeader=true ..));

        }
        // stiamo comunque scorrendo gli elementi, aggiungiamo quello appena trovato
        items.add(new PersonEntry( ... defile isHeader = false ....);
        previousCountry = currentCountry;
        i++;
        cursor.moveToNext();
    }
    cursor.close();
    Log.d(this.getClass().getSimpleName(),"readHeaders end");


}

所以我重写了 getView、bindView 和 newView 以膨胀正确的布局并绑定(bind)基于 realPos-position Cursor 的 View 。

该方法有效,但它真的很昂贵:它需要详细说明整个表,而且我有很多记录。 我正在寻找的是一种在滚动 ListView 时映射 realPosition -> fakePosition 的简单方法,但我认为这些方法太复杂了,我认为如果 getView 不是线性的(快速滚动?)它们会中断。

解决方案: 1) 按 COUNTRY_NAME 查询排序。向下滚动时 real_cursor_position =(请求的位置 - “国家变化#(?)”)。如果在 real_position 中翻译的请求位置出现在具有不同 country_name 的项目之后,则它是一个标题。我认为,除非有棘手的解决方案,否则在向下滚动拳头和向上滚动时它会破裂。 ... 仅此而已

还有其他解决方案吗?

编辑:另一个问题是,如果不扫描整个表,我无法预测 adapter.getCount() 返回的 View 数。

最佳答案

我已经编写了简单适配器的 getView 方法来向您展示如何构建一个 ListView,其中的 header 将具有相同国家/地区的项目分组。这将假定标题 View 在每一行的布局中显示/隐藏它作为当前行的要求。同样的事情可以通过使用 getItemViewType 方法来完成,并在绑定(bind)适配器的各个部分方面做更多的工作。

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        if (convertView == null) {
            convertView = mInflater.inflate(
                    R.layout.rowlayout, parent, false);
        }
        // for simplicity, the header it's just a TextView
        TextView header = (TextView) convertView
                .findViewById(R.id.headerPart);
        // also for simplicity, the row content it's just a TextView
        TextView rowText = (TextView) convertView
                .findViewById(R.id.normalPart);
        // set the data for the row
        mCursor.moveToPosition(position);
        rowText.setText(mCursor.getString(mCursor.getColumnIndex("name")));
        // this is not the first position               
        if (position - 1 >= 0) {
            // if there is a previous position see if it has the same
            // country(in which case you already had set the header)
            String currentCountry = mCursor.getString(mCursor
                    .getColumnIndex("country"));
            mCursor.moveToPosition(position - 1);
            String previousCountry = mCursor.getString(mCursor
                    .getColumnIndex("country"));
            if (currentCountry.equalsIgnoreCase(previousCountry)) {
                // the countries are the same so abort everything as we
                // already set the header on one of previous rows
                header.setVisibility(View.GONE);
            } else {
                // this is the first occurrence of this country so show the
                // header
                header.setVisibility(View.VISIBLE);
                header.setText(currentCountry);
            }
        } else {
            // this is position 0 and we need a header here
            header.setVisibility(View.VISIBLE);
            header.setText(mCursor.getString(mCursor
                    .getColumnIndex("country")));
        }
        return convertView;
    }

关于android - ListView/CursorAdapter 动态生成列表标题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14784186/

相关文章:

java - 如何在android中设置自定义颜色

java - 安卓 ZipInputStream : only DEFLATED entries can have EXT descriptor

visual-studio - Visual Studio 2017 在构建和调试过程中太慢

java - JProfiler : knowing which method is calling for java objects

android - 如何在ListView中绘制水平线?

android - ActionBar 和 ListView 行之间的空间

android - Android 上的 facebook api - 如何获取用户拥有的好友数量?

java - 什么更有效率?存储变量引用与不存储变量引用(Android 中的上下文)

c++ - 优化只有 3 个不同值的数组?如何设计?

java - Android ListView 不显示任何内容