web-dev-qa-db-ja.com

CursorWindowを割り当てることができませんでした

私はAndroidアプリでSQLiteデータベースを操作しています。20万行14列の事前入力されたデータベースから読み取りました。エントリは単語です。データ型すべての列のテキストです。11文字までの単語(例:ABANDONMENT)のクエリは正常に機能しますが、12文字以上(例:ABANDONMENTS)の場合、アプリはクラッシュします。logcatは次のとおりです。

Could not allocate CursorWindow '//data//data//com.example.myapp//databases//database.sqlite' of size 2097152 due to error -12.
threadid=11: thread exiting with uncaught exception (group=0x40adf9f0)
FATAL EXCEPTION: Thread-2883
Android.database.CursorWindowAllocationException: Cursor window allocation of 2048 kb failed. # Open Cursors=861 (# cursors opened by this proc=861)
at Android.database.CursorWindow.<init>(CursorWindow.Java:104)
at Android.database.AbstractWindowedCursor.clearOrCreateWindow(AbstractWindowedCursor.Java:198)
at Android.database.sqlite.SQLiteCursor.fillWindow(SQLiteCursor.Java:162)
at Android.database.sqlite.SQLiteCursor.getCount(SQLiteCursor.Java:156)
at Android.database.AbstractCursor.moveToPosition(AbstractCursor.Java:161)
at Android.database.AbstractCursor.moveToFirst(AbstractCursor.Java:201)
at com.example.myapp.MainActivity.query(MainActivity.Java:815)
at com.example.myapp.MainActivity$2.run(MainActivity.Java:356)
at Java.lang.Thread.run(Thread.Java:856)

コード:

query = "select * from words where col_1 = \"" + (myWord)+ "\";";
cursor = database.rawQuery(query, null);
if (cursor != null)                                          
    cursor.moveToFirst(); // line 815
if (!cursor.isAfterLast()) {
    do {
        for (i = 1; i < cursor.getColumnCount(); i++) {
            temp = cursor.getString(i);
            //other stuff
        }
    } while (cursor.moveToNext());
    cursor.close();
}

では、エラーは何を意味し、アプリがクラッシュするのはなぜですか?

15
Frozen Crayon

私はループで探求していました。そして、ループの外側ではなく内側でカーソルを閉じると、問題が解決しました。

13
Frozen Crayon

エラー-12はカーソルリークを意味します。 plsは次のようにそれを閉じてみてください:

try {....} finally {  cursor.close();}
18
will

Androidカーソルは、すべてのクエリ結果をメモリに読み込み、そのデータには1MBの制限があります。

この制限が選択されたのは、この量のデータにより、モバイルデバイスでのアプリの実行が遅くなる可能性があるためです。

可能であれば、次のことを行う必要があります。

  • コードではなくSQLで計算を行います。
  • 必要なデータのみをクエリします(つまり、SELECT *を使用せず、必要な列のみを取得し、WHEREフィルターを使用します)。
  • 少しずつデータを読み取ります。
4
CL.