2011-11-14 5 views
0

AsyncTask私はコンテンツプロバイダにクエリを行い、そのタスクのonPostExecute()でいくつかの追加処理を行います。再現するのが非常に難しい例外のスタックトレースがありますが、条件を守り、コードを修正したいと思います。コードは次のとおりです。このArrayIndexOutOfBounds例外がどのようにスローされているかわかりません

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スレッドで を実行しているため可能ではありません。これは、変数に という新しい値が割り当てられている唯一の場所です。 UIスレッドで実行されているonPostExecuteの性質上、このコードは他の場所で同時に実行することはできません。

何か不足していますか?

+0

ちょうどループの前に 'mIds'の長さを記録します:

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; 

ここに私のアプローチのためのバックアップです。次に、mIds [i ++]への代入に条件付きブレークを置き、 'i> = mIds.length'ならブレークします。それが壊れたときに、 'カーソル'が長さを変更したのか、他に何が起こっているのか、 'mIds'がどうにか再割り当てされたかどうかを確認することができます。 –

+0

私はこの情報を現在ログに記録せず、再現できませんでした(バグレポートが1つあります)ので、条件を守るためのコードを追加することができます。 –

答えて

1

これは、完全なコードを見ることなく、そのループと間違っているかを確認するのは難しいのですが、私はdocsから注意してください。

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

+0

すべての答えのうち、私はこれが最も近いと思います。それは、コードを少し深く見せてくれました。ループは実際には 'MyAdapter.changeCursor(cursor)'から呼び出されたメソッドにあり、ループを含むメソッドはAFTER 'super.changeCursor(cursor)'と呼ばれます。 'changeCursor()'は 'onPostExecute()'で呼び出されるメソッドです。今、私の考えは 'super.changeCursor()'の後で、カーソルはアダプタにアクセスする他のスレッドが利用できるようになり、それらのスレッドはループ中に位置をリセットしなければならないということです。 –

1

これを試してみてください。

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

あなたはなぜi ++を動かすことがここで違いを生むと思うのかを詳しく説明できますか? –

+0

よく私は使用される前にその追加を信じています。したがって、それは1で始まり(0とは対照的に)、+ 1で終了するはずです。私は間違っている可能性があり、テストする私の目の前にコンパイラを持っていない –

+1

これは、後置インクリメント演算子が動作する方法ではありません。 –

0

私はいつもこのようにしています。ほとんどの問題を避けるためだと思われる。
Is Android Cursor.moveToNext() Documentation Correct?
Does finally always execute in Java?

+0

ありがとうございます。それは強制終了を避けるでしょうが、なぜこの例外がマスクされているのか理解することにもっと興味があります。 –

+0

ええ、それはいつも理解して良いです。とにかく、私は 'moveToNext()'に問題があったと思います...これを試してみてください:whileの前に 'moveToFirst()'を追加し、do-whileの間に変更してください。それが役立つかどうかを見てください。また、私は 'mIds [i ++]'から 'i ++'を取り去ります。 –

関連する問題