Android Cursor.moveToNext()文档是否正确?

时间:2011-05-12 23:36:36

标签: android sqlite

boolean android.database.Cursor.moveToNext()文档说:

http://developer.android.com/reference/android/database/Cursor.html#moveToNext%28%29

将光标移动到下一行。

如果光标已经超过结果集中的最后一个条目,则此方法将返回false。


但是,我的书说要从光标中提取数据:

Cursor myCursor = myDatabase.query(...);
if (myCursor.moveToFirst()) {
    do {
    int value = myCursor.getInt(VALUE_COL);
    // use value
    } while (myCursor.moveToNext());
}

谁是对的?这两者都不可能是真的。如果你看不到矛盾,想象一下myCursor从查询中返回了1行。对getInt()的第一次调用将起作用,但随后moveToNext()将返回true,因为它不是“已经”超过结果集中的最后一个条目。所以现在光标将超过最后一个条目,第二次调用getInt()会做一些未定义的事情。

我怀疑文档是错误的,应该改为:

如果光标“已经在”结果集中的最后一个条目,则此方法将返回false。

在moveToNext()方法返回false之前,光标必须已经是PAST(不是AT)的最后一个条目吗?

没有Snark请

5 个答案:

答案 0 :(得分:21)

一个更简单的习语是:

Cursor cursor = db.query(...);
while (cursor.moveToNext()) {
    // use cursor
}

这是因为初始光标位置为-1,请参阅Cursor.getPosition()文档。

您还可以使用此Google Code Search query在Android源代码中找到游标的用法。 SQLite数据库和内容提供者中的游标语义相同。

参考文献:this question

答案 1 :(得分:6)

来自API的逐字:

  

返回:       此举是否成功。

     

所以,这意味着:

第一行中的光标 - > moveToNext() - >光标在第二行 - >没有第二行 - >返回错误


如果您需要详细信息,请转到来源:http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.3.3_r1/android/database/AbstractCursor.java#AbstractCursor.moveToNext%28%29

public final boolean moveToNext() {
  return moveToPosition(mPos + 1);
}

public final boolean moveToPosition(int position) {
    // Make sure position isn't past the end of the cursor
    final int count = getCount();
    if (position >= count) {
        mPos = count;
        return false;
    }

答案 2 :(得分:2)

我认为我倾向于远离基于隐藏假设的解决方案,例如:我希望sqlite永远不会改变api,并且游标总是从第一项开始。

此外,我几乎总能用for语句替换while语句。所以我的解决方案显示了我期望光标开始的内容,并避免使用while语句:

for( boolean haveRow = c.moveToFirst(); haveRow; haveRow = c.moveToNext() ) {
...
}

为什么显示游标需要从第一行开始,就在你可能正在调试自己的代码的6个月之后,并且会想知道你为什么不明确这样做以便你可以轻松地调试它。 / p>

答案 3 :(得分:2)

它似乎取决于AbstractCursor的Android实现,它在Jellybean中仍然存在。

我实施了以下单元测试,以使用MatrixCursor向我自己演示问题:

@Test
public void testCursor() {
  MatrixCursor cursor = new MatrixCursor(new String[] { "id" });
  for (String s : new String[] { "1", "2", "3" }) {
    cursor.addRow(new String[] { s });
  }

  cursor.moveToPosition(0);
  assertThat(cursor.moveToPrevious(), is(true));

  cursor.moveToPosition(cursor.getCount()-1);
  assertThat(cursor.moveToNext(), is(true));

  assertThat(cursor.moveToPosition(c.getCount()), is(true));
  assertThat(cursor.moveToPosition(-1), is(true));
}

所有断言都失败了,与moveToNext,moveToPrevious和moveToPosition的文档相反。

在API 16中读取AbstractCursor.moveToPosition(int position)的代码,它似乎是有意的行为,即在这些情况下方法显式返回false,与文档相反。

作为旁注,由于Android代码在野外的现有设备上无法更改,我采用编写代码的方法来匹配现有Android实现的行为,而不是文档。即。在实现我自己的Cursors / CursorWrappers时,我重写方法并编写自己的javadoc来描述与现有文档的偏离。这样,我的Cursors / CursorWrappers仍然可以与现有的Android游标互换,而不会破坏运行时行为。

答案 4 :(得分:0)

返回布尔值的Cursor.moveToNext()仅在它不会将光标移过数据集中的最后一个条目时才有用。因此,我已经提交了关于文档问题跟踪器的错误报告。

https://issuetracker.google.com/issues/69259484

它推荐以下句子:
“如果当前(执行时)条目是集合中的最后一个条目,并且没有下一个条目,则此方法将返回false。”