【问题标题】:Stumped as to how this ArrayIndexOutOfBounds exception is being thrown困惑于如何抛出这个 ArrayIndexOutOfBounds 异常
【发布时间】:2011-11-15 04:59:47
【问题描述】:

我有一个AsyncTask 查询内容提供者并在该任务的onPostExecute() 中进行一些额外的处理。我有一个很难重现的异常的堆栈跟踪,但我想防范这种情况或修复代码。代码如下:

int i = 0;
mIds = new long[cursor.getCount()];
while (cursor.moveToNext()) {
    mIds[i++] = cursor.getLong(COLUMN_ID);
}

崩溃发生在循环中的行上。在我看来,这可能发生的唯一方式 是如果:

  1. cursor.getCount() 返回的计数不正确。
  2. cursor 在此循环执行时被更改,但我认为这是不可能的 因为cursor 是一个局部变量。也许cursor 背后的某些东西发生了我不知道的变化。
  3. mIds 已更改。这不应该是可能的,因为我们正在运行 在 UI 线程上,这是唯一分配该变量的地方 一个新的价值。由于onPostExecute 在 UI 线程上运行的性质,这段代码不可能同时在其他地方运行,对吧?

我错过了什么吗?

【问题讨论】:

  • 在循环之前记录mIds 的长度。然后在对 mIds[i++] 的赋值处放置一个条件中断,如果i >= mIds.length 则中断。当它中断时,您可以检查 mIds 是否以某种方式重新分配,cursor 是否更改了长度,或者可能发生的其他情况。
  • 我目前没有记录此信息并且无法重现(收到一份错误报告),所以我希望我可以添加代码来防范这种情况。

标签: android android-cursor


【解决方案1】:

如果不查看完整代码,很难看出该循环有什么问题,但我注意到docs:

游标实现不需要同步,因此使用来自多个线程的游标的代码应该在使用游标时执行自己的同步。

【讨论】:

  • 在所有答案中,我认为这个是最接近的。这让我更深入地研究了代码。循环实际上是在从MyAdapter.changeCursor(cursor) 调用的方法中,并且包含循环的方法在super.changeCursor(cursor) 之后调用。 changeCursor() 是在onPostExecute() 中调用的方法。现在,我的想法是,在 super.changeCursor() 之后,光标对访问适配器的其他线程可用,并且这些线程必须在我的循环期间重置位置。
【解决方案2】:

试试这个:

int i = 0;
mIds = new long[cursor.getCount()];
while (cursor.moveToNext()) {
    mIds[i] = cursor.getLong(COLUMN_ID);
    i++;
}

【讨论】:

  • 您能否详细说明为什么您认为移动 i++ 会在这里有所作为?
  • 嗯,我相信它在使用前添加。因此,它将从 1 开始(而不是 0)并在 +1 结束于它应该在的位置。我可能是错的,我面前没有编译器来测试
【解决方案3】:

根据我的经验,我总是这样做。似乎可以避免大多数问题。

Cursor cursor = null;

try
{
    cursor = getDb().rawQuery(query, params); // your call to database here...
    if (cursor == null || cursor.getCount() == 0)
        return false;

    cursor.moveToFirst();

    mIds = new long[cursor.getCount()];
    int i = 0;

    do
    {
        mIds[i] = cursor.getLong(COLUMN_ID);
        i++;
    } while (cursor.moveToNext())
} catch(Exception e) {
    // Do error handling
    return false;
}
finally
{
    closeCursor(cursor);
    cursor = null;
}

return true;

这是我的方法的备份:
Is Android Cursor.moveToNext() Documentation Correct?
Does finally always execute in Java?

【讨论】:

  • 谢谢。这将避免强制关闭,但我更感兴趣的是理解为什么会发生这个异常而不是掩盖它。
  • 是的,理解总是好的。无论如何,我记得我对moveToNext() 有问题...试试这个:在while 之前添加moveToFirst(),然后更改while 来做。看看是否有帮助。另外,我还会将i++ 与mIds[i++] 分开。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-10
  • 2011-05-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多