0

コンテンツ プロバイダーにAsyncTaskクエリを実行し、onPostExecute()そのタスクで追加の処理を行う があります。再現するのが非常に難しい例外のスタック トレースがありますが、この状態から保護するか、コードを修正したいと考えています。コードは以下のとおりです。

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

ループ内の回線でクラッシュが発生しています。私の見方では、これが発生する唯一の方法は次の場合です。

  1. cursor.getCount()間違ったカウントを返しています。
  2. cursorcursorこのループの実行中に変更されますが、ローカル変数であるため、可能ではないと思います。おそらくcursor、私が気付いていない根本的な何かが変わったのでしょう。
  3. mIds変更されました。UI スレッドで実行していて、変数に新しい値が割り当てられる唯一の場所であるため、これは不可能です。UI スレッドで実行するという性質上onPostExecute、このコードを別の場所で同時に実行することはできないはずですよね?

何か不足していますか?

4

3 に答える 3

1

これを試して:

int i = 0;
mIds = new long[cursor.getCount()];
while (cursor.moveToNext()) {
    mIds[i] = cursor.getLong(COLUMN_ID);
    i++;
}
于 2011-11-14T20:23:28.037 に答える
1

完全なコードを見ずにそのループの何が問題なのかを確認するのは難しいですが、ドキュメントからメモします:

カーソルの実装は同期する必要がないため、複数のスレッドから Cursor を使用するコードは、Cursor を使用するときに独自の同期を実行する必要があります。

于 2011-11-14T20:26:01.730 に答える
0

私の経験から、私はいつもこのようにしています。ほとんどの問題を回避するようです。

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;

これが私のアプローチのバックアップです:
Android Cursor.moveToNext()ドキュメントは正しいですか?
最終的には常にJavaで実行されますか?

于 2011-11-14T20:39:31.283 に答える