Android:Cursor.getColumnIndex()在行循环中是不变的吗?

时间:2017-01-25 11:23:02

标签: android sqlite android-cursor

似乎android.database.Cursor.getColumnIndex(String)应该在行循环中保持不变。

然而,我看到大量代码执行的操作如下:

try (Cursor cursor = database.query(...)) {
  while (cursor.moveToNext()) {
    String aString = cursor.getString(cursor.getColumnIndex(aColumnName));
    // ... other loop code and more repeated use of getColumnIndex()
  }
}

这看起来很愚蠢和浪费,除非getColumnIndex()的结果真的随着cursor.moveToNext()的调用而变化 - 并且这个调用应该像循环一样被提升出来:

try (Cursor cursor = database.query(...)) {
  int aStringIdx = cursor.getColumnIndex(aColumnName);
  while (cursor.moveToNext()) {
    String aString = cursor.getString(aStringIdx);
    // ... other loop code
  }
}

或在最坏的情况下(假设getColumnIndex()要求您在有效的数据行上):

try (Cursor cursor = database.query(...)) {
  if (cursor.moveToFirst()) {
    int aStringIdx = cursor.getColumnIndex(aColumnName);
    do {
      String aString = cursor.getString(aStringIdx);
      // ... other loop code
    } while (cursor.moveToNext());
  }
}

那么这里的真实故事是什么?

2 个答案:

答案 0 :(得分:1)

getColumnIndex()moveToNext()方法之间存在无依赖。(您的第二个选项将是最佳方法)
您可以通过查看CursorAbstractCursor方法来源下moveToPosition()中的getColumnIndex()界面实施来查看此内容。

答案 1 :(得分:1)

  

我看到每次都通过行循环得到getColumnIndex,这完全没有意义

也许是因为当我们执行查询时,我们会收到SQLiteCursor个实例,而不是AbstractCursor。如果我们查看源代码,我们可以在内部找到chache:

  @Override
    public int getColumnIndex(String columnName) {
        // Create mColumnNameMap on demand
        if (mColumnNameMap == null) {
            String[] columns = mColumns;
            int columnCount = columns.length;
            HashMap<String, Integer> map = new HashMap<String, Integer>(columnCount, 1);
            for (int i = 0; i < columnCount; i++) {
                map.put(columns[i], i);
            }
            mColumnNameMap = map;
        }

       //...
    }

另一方面,访问变量(如示例2)比计算哈希键以获取索引更快。可能是相关的,取决于桌子的大小。

编辑:在具有复杂查询的大型表上进行测试,似乎改进了5%,在我的情况下不值得进行更改。一般来说,HashMap缓存已经足够了。