19

SQLハンドラーに問題があります

A SQLiteConnection object for database '/data/data/.../databases/queueManager' was leaked!  Please fix your application to end transactions in progress properly and to close the database when it is no longer needed.

Androidhive チュートリアルから取得し、自分の使用に合わせてカスタマイズ

テーブルは次のようになります

+ ----------------------------------------------------------- +
: DATABASE_ID : DATABASE_QID : DATABASE_QUEUE : DATABASE_DATE :
+ ----------------------------------------------------------- +

コード

   DBQueue searchDBqid(int id) {
       SQLiteDatabase db = this.getReadableDatabase();

        String selectQuery = "SELECT  * FROM " + TABLE_QUEUE + " WHERE " + DATABASE_QID + " = " + id; 

           Cursor cursornum = db.rawQuery(selectQuery, null);
           int dk = cursornum.getCount();
           cursornum.close();

           if (dk >0) {
               Cursor cursor = db.query(TABLE_QUEUE, new String[] { DATABASE_ID,
                       DATABASE_QID, DATABASE_QUEUE, DATABASE_DATE }, DATABASE_QID + "=?",
                       new String[] { String.valueOf(id) }, null, null, null, null);

               if (cursor != null) cursor.moveToFirst();

               DBQueue dbqueue = new DBQueue(Integer.parseInt(cursor.getString(0)),
                       cursor.getString(1), cursor.getString(2), cursor.getString(3));
               return dbqueue;
           }

       db.close();
       return null;
   }

   DBQueue getDBQueue(int id) {
       SQLiteDatabase db = this.getReadableDatabase();

       Cursor cursor = db.query(TABLE_QUEUE, new String[] { DATABASE_ID,
               DATABASE_QID, DATABASE_QUEUE }, DATABASE_ID + "=?",
               new String[] { String.valueOf(id) }, null, null, null, null);
       if (cursor != null)
           cursor.moveToFirst();

       DBQueue dbqueue = new DBQueue(Integer.parseInt(cursor.getString(0)),
               cursor.getString(1), cursor.getString(2), cursor.getString(3));
       return dbqueue;
   }


   public String getAllqid() {
       Time today = new Time(Time.getCurrentTimezone());
       today.setToNow();

       String selectQuery = "SELECT  * FROM " + TABLE_QUEUE + " WHERE " + DATABASE_DATE + " = '" + today.format("%d %m %Y") + "'";

       SQLiteDatabase db = this.getWritableDatabase();
       Cursor cursor = db.rawQuery(selectQuery, null);

       StringBuilder sb = new StringBuilder();       
       if (cursor.moveToFirst()) {
           do {
               if (sb.length() > 0) sb.append(',');
               sb.append(cursor.getString(1));
           } while (cursor.moveToNext());
       }

       String result = sb.toString();
       return result;
   }
   public void deleteDatedDBQueue() {
        Time today = new Time(Time.getCurrentTimezone());
        today.setToNow();
        String selectQuery = "SELECT  * FROM " + TABLE_QUEUE + " WHERE " + DATABASE_DATE + " != '" + today.format("%d %m %Y") + "'"; ;

        SQLiteDatabase db = this.getWritableDatabase();
        Cursor cursor = db.rawQuery(selectQuery, null);

        if (cursor.moveToFirst()) {
            do {
                db.delete(TABLE_QUEUE, DATABASE_ID + " = ?",
                       new String[] { String.valueOf(Integer.parseInt(cursor.getString(0))) });
            } while (cursor.moveToNext());
        }
        db.close();
    }
   public int getDBQueueCount() {
       String countQuery = "SELECT  * FROM " + TABLE_QUEUE;
       SQLiteDatabase db = this.getReadableDatabase();
       Cursor cursor = db.rawQuery(countQuery, null);
       cursor.close();

       return cursor.getCount();
   }
}

誰かがこのリークを修正する方法を教えてもらえますか?

完全なコード: http://ijailbreak.me/databasehandler.txt

4

4 に答える 4

51

Cursor終了したら、それぞれを閉じる必要があります。これを行う従来の方法は次のとおりです。

Cursor cursor = db.query(...);
try {
    // read data from the cursor in here
} finally {
    cursor.close();
}

しかし今、try-with-resourcesを使用すると、はるかに簡潔になります。

try (Cursor cursor = db.query(...)) {
    // read data from the cursor in here
}
于 2012-10-09T14:05:56.380 に答える
8

何度かカーソルを閉じるのを忘れた場合は、完了したら常にカーソルを閉じるようにしてください。

たとえば、2番目のクエリはカーソルを閉じません。わかりやすくするためにTODOを実行しました。

また、一度完了したら閉じないでSQLiteDatabaseください。また、デザインを変更してシングルトンにする場合は、を閉じてリークを回避する必要はありません。getDBQueuegetAllqidgetDBQueueCountSQLiteOpenHelperSQLiteDatabase

   DBQueue searchDBqid(int id) {
       SQLiteDatabase db = this.getReadableDatabase();

        String selectQuery = "SELECT  * FROM " + TABLE_QUEUE + " WHERE " + DATABASE_QID + " = " + id; 

           Cursor cursornum = db.rawQuery(selectQuery, null);
           int dk = cursornum.getCount();
           cursornum.close();

           if (dk >0) {

               // TODO: Close this cursor!
               Cursor cursor = db.query(TABLE_QUEUE, new String[] { DATABASE_ID,
                       DATABASE_QID, DATABASE_QUEUE, DATABASE_DATE }, DATABASE_QID + "=?",
                       new String[] { String.valueOf(id) }, null, null, null, null);

               if (cursor != null) cursor.moveToFirst();

               DBQueue dbqueue = new DBQueue(Integer.parseInt(cursor.getString(0)),
                       cursor.getString(1), cursor.getString(2), cursor.getString(3));
               return dbqueue;
           }

       db.close();
       return null;
   }
于 2012-10-09T13:54:48.287 に答える
1

データベース (読み取り可能または書き込み可能) を開くたびに、メモリ リソースを使用するカーソルは、".close();" を使用して割り当てを解除する必要があります。その使用が各データベース機能で終了した後、例えば:

 if (cursor != null) cursor.moveToFirst();

               DBQueue dbqueue = new DBQueue(Integer.parseInt(cursor.getString(0)),
                       cursor.getString(1), cursor.getString(2), cursor.getString(3));
               return dbqueue;
           }
cursor.close();

       db.close();
       return null;
   }

DBQueue getDBQueue(int id) {
       SQLiteDatabase db = this.getReadableDatabase();

       Cursor cursor = db.query(TABLE_QUEUE, new String[] { DATABASE_ID,
               DATABASE_QID, DATABASE_QUEUE }, DATABASE_ID + "=?",
               new String[] { String.valueOf(id) }, null, null, null, null);
       if (cursor != null)
           cursor.moveToFirst();

       DBQueue dbqueue = new DBQueue(Integer.parseInt(cursor.getString(0)),
               cursor.getString(1), cursor.getString(2), cursor.getString(3));
cursor.close();
db.close();
       return dbqueue;
   }

等々....!!

于 2016-07-26T04:03:24.670 に答える
0

初めてデータベースを開き、最後にこのコードを配置します。

 @Override
        protected void onDestroy() {
            // TODO Auto-generated method stub
         mdb.close();   
         super.onDestroy();
        }
于 2013-03-29T09:07:39.897 に答える