【问题标题】:Is Android Cursor.moveToNext() Documentation Correct?Android Cursor.moveToNext() 文档是否正确?
【发布时间】:2011-05-12 23:36:36
【问题描述】:

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

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

将光标移动到下一行。

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


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

光标 myCursor = myDatabase.query(...); if (myCursor.moveToFirst()) { 做 { int 值 = myCursor.getInt(VALUE_COL); // 使用值 } 而 (myCursor.moveToNext()); }

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

我怀疑文档有误,应该改为:

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

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

请不要打蛇

【问题讨论】:

  • 我认为如果您只使用 myCursor.moveToNext(),您会将它放在 while 循环的开头,例如 while(myCursor.moveToNext()){...}。你从第一个位置开始,所以没有矛盾。
  • 这本书的作者不同意你的方法。他们声称您需要 if(myCursor.moveToFirst()) 结果集为空的情况。如果您从 MoveToNext() 开始,则光标的位置未定义,您的代码将始终失败。
  • 我猜他可能是对的。我只是快速搜索了我的代码,实际上我总是先执行 movetofirst 然后执行 do{}while() 循环。仍然不一定意味着矛盾 - 它可能是光标甚至没有定义起始位置,直到您移动到特定条目(第一个或其他)。
  • 我认为你错过了矛盾。作者声称,如果您是“AT”最后一个条目,则可以测试 moveToNext() 的结果,如果为真,则与文档的声明相矛盾,如果“已经过去”,它将返回 false。

标签: android sqlite


【解决方案1】:

一个更简单的成语是:

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

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

您还可以通过Google Code Search query 在 Android 源代码本身中找到光标的用法。 SQLite 数据库和内容提供程序中的光标语义相同。

参考:this question.

【讨论】:

    【解决方案2】:

    API 中的逐字记录:

    返回: 移动是否成功。


    所以,这意味着:

    光标在第一行 -> moveToNext() -> 光标在第二行 -> 没有第二行 -> 返回 false


    如需了解详情,请前往来源: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;
        }
    

    【讨论】:

    • @user 好吧,只有当您对措辞非常严格时,请考虑“如果光标已经超过最后一个条目”是指更改之前的时刻而不是之后的时刻,如果您不考虑我引用的部分,这是唯一重要的部分:“返回:移动是否成功。”
    • “已经过去”是指在调用之前,而不是之后,否则我们必须重新定义英文单词“already”。严格的含义在文档中是必不可少的,因为模棱两可的词充其量是没有帮助的。 “返回:移动是否成功。”,没有任何意义,因为在我能看到的任何地方都没有定义成功,并且将一个移动到数据集末尾之外通常被定义为成功。我建议简单地说明文档是错误的并建议对其进行修复。
    【解决方案3】:

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

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

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

    为什么显示游标需要从第一行开始,在 6 个月后您可能正在调试自己的代码,并且会想知道为什么您没有明确说明以便可以轻松调试它。

    【讨论】:

      【解决方案4】:

      这似乎取决于 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 实现的行为的方法,而不是文档。 IE。在实现我自己的 Cursors / CursorWrappers 时,我重写了这些方法并编写了自己的 javadoc 来描述与现有文档的不同之处。这样,我的 Cursors / CursorWrappers 可以与现有的 Android 游标互换,而不会破坏运行时行为。

      【讨论】:

        【解决方案5】:

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

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

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-04-22
          • 1970-01-01
          • 2019-10-17
          • 2016-05-01
          • 2016-08-07
          • 1970-01-01
          • 2011-07-06
          • 1970-01-01
          相关资源
          最近更新 更多