Android SQLite 泄露
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12801602/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Android SQLite leaked
提问by Kirma
i having problem with sql handler
我的 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.
taken from Androidhive tutorial and customized to my use
取自 Androidhive 教程并根据我的使用情况进行定制
the table looks like
桌子看起来像
+ ----------------------------------------------------------- +
: DATABASE_ID : DATABASE_QID : DATABASE_QUEUE : DATABASE_DATE :
+ ----------------------------------------------------------- +
The code
编码
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();
}
}
Can someone please tell me how to fix this leak ?
有人可以告诉我如何解决这个泄漏吗?
full code: http://ijailbreak.me/databasehandler.txt
回答by Graham Borland
Each Cursor
should be closed when you're finished with it. The traditional way to do this is:
Cursor
完成后,每个都应该关闭。这样做的传统方法是:
Cursor cursor = db.query(...);
try {
// read data from the cursor in here
} finally {
cursor.close();
}
But now, with try-with-resources, it can be much more concise:
但是现在,使用try-with-resources,它可以更加简洁:
try (Cursor cursor = db.query(...)) {
// read data from the cursor in here
}
回答by Ian Warwick
You forget to close your cursors on several occasions, make sure you always close the cursor when your done.
您多次忘记关闭光标,请确保在完成后始终关闭光标。
For instance, the second query does not close the cursor, I have TODO'd it for clarity
例如,第二个查询没有关闭游标,为了清楚起见,我已经完成了
Also you do not close theSQLiteDatabase
once your done in getDBQueue
, getAllqid
and getDBQueueCount
, if you change your design to make your SQLiteOpenHelper
a singleton then you won't need to close the SQLiteDatabase
and avoid the leak
此外,SQLiteDatabase
一旦完成,您就不会关闭getDBQueue
,getAllqid
并且getDBQueueCount
,如果您更改设计以使其SQLiteOpenHelper
成为单身人士,那么您将不需要关闭SQLiteDatabase
并避免泄漏
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;
}
回答by Ian Warwick
Each time you open a database(readable or writable) and cursor which uses memory resources has to be deallocated by using ".close();" after its usage ends in each database function eg:
每次打开数据库(可读或可写)时,必须使用“.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;
}
and so on....!!
等等....!!
回答by AnilPatel
first time open database and last put this code.
第一次打开数据库,最后放这段代码。
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
mdb.close();
super.onDestroy();
}