Question

I have an AsyncTask that queries a content provider and does some additional processing in the onPostExecute() of that task. I have a stack trace for an exception that is very hard to reproduce, but I would like to guard against the condition or fix the code. The code is below:

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

The crash is happening on the line in the loop. The way I see it, the only way this could happen is if:

  1. cursor.getCount() is returning an incorrect count.
  2. cursor is changed while this loop is executing, but I don't think that's possible because cursor is a local variable. Perhaps something underlying the cursor has changed that I'm not aware of.
  3. mIds has changed. This shouldn't be possible because we are running on the UI thread and this is the only place in which that variable is assigned a new value. By the nature of onPostExecute running on the UI thread, it shouldn't be possible for this code to be running somewhere else at the same time, right?

Am I missing something?

Was it helpful?

Solution

It's difficult to see what is wrong with that loop without seeing the full code but I note from the docs:

Cursor implementations are not required to be synchronized so code using a Cursor from multiple threads should perform its own synchronization when using the Cursor.

OTHER TIPS

try this:

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

Drawing from my experiences, I always do it like this. Seems to avoid most problems.

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;

Here's backup for my approach:
Is Android Cursor.moveToNext() Documentation Correct?
Does finally always execute in Java?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top