SQLite Android 泄露
SQLite Android Leaked
我有这个方法来读取数据库:
class BDUtilities
private Context context;
private BDHelper bd;
private SQLiteDatabase db_reader;
private SQLiteDatabase db_writer;
public BDUtilities(Context context){
this.context = context;
this.bd = new BDHelper(context);
this.db_reader = bd.getReadableDatabase();
this.db_writer = bd.getWritableDatabase();
}
public ArrayList<Boolean> getPreferences() {
ArrayList<Boolean> resultados = new ArrayList<Boolean>();
if (checkBeforeUse()) {
try {
int user_id = getUserId();
Cursor c = db_reader.rawQuery("select cb_save_login, cb_save_pic_after_share," +
"cb_upload_anonym, cb_init_cat_pref, user_id from prefs where user_id = ?", new String[] { String.valueOf(user_id) });
if (c.getCount() > 0){
c.moveToFirst();
resultados.add(parse(c.getString(c.getColumnIndex("cb_save_login"))));
resultados.add(parse(c.getString(c.getColumnIndex("cb_save_pic_after_share"))));
resultados.add(parse(c.getString(c.getColumnIndex("cb_upload_anonym"))));
resultados.add(parse(c.getString(c.getColumnIndex("cb_init_cat_pref"))));
c.close();
} else { c.close(); }
}
finally {
//both error
//bd.close();
//db_reader.close(); //error:
//01-12 06:05:36.370: E/AndroidRuntime(1681): java.lang.IllegalStateException:
//attempt to re-open an already-closed object: SQLiteDatabase:
//data/data/com.example.photopt/databases/projeto_ddm.db
}
}
return resultados;
}
我试图关闭 db_reader 有 bd_reader = database.getReadableDatabase(); 但有错误。
这段代码:
这不是 return 错误,但经过一些使用后显示:
01-12 05:51:29.647: W/SQLiteConnectionPool(1762): A SQLiteConnection
object for database
'/data/data/com.example.photopt/databases/projeto_ddm.db' was leaked!
Please fix your application to end transactions in progress properly
and to close the database when it is no longer needed.
试试这个....
if (c.getCount() > 0){
c.moveToFirst();
resultados.add(parse(c.getString(c.getColumnIndex("cb_save_login"))));
resultados.add(parse(c.getString(c.getColumnIndex("cb_save_pic_after_share"))));
resultados.add(parse(c.getString(c.getColumnIndex("cb_upload_anonym"))));
resultados.add(parse(c.getString(c.getColumnIndex("cb_init_cat_pref"))));
c.close();
bd.close();
} else {
c.close();
bd.close();
}
你没有关闭db_writer
不管不用,初始化时还是打开的
this.db_writer = bd.getWritableDatabase();
建议也关闭,否则连接泄露
this.db_writer.close();
更好的方法是编写一个您可以调用的辅助方法:
public void CloseDb()
{
if(db_writer.isOpen())
db_writer.close();
if(db_reader.isOpen())
db_reader.close();
}
然后您可以在适当的地方调用 CloseDb()
(仍然需要像往常一样关闭游标)。
此方法在关闭前检查其打开状态,因此不会尝试关闭它两次。
您通常不会从内部关闭 Databasehelper
。通常一旦你在 activity
中使用完它。 (完成后从 activity 调用 CloseDb()
,也就是 onPause
或 onDestroy
。)
此代码阻止了泄漏并修复了游标问题。
public class DatabaseHelper extends SQLiteOpenHelper {
private static DatabaseHelper sInstance;
private static final String DATABASE_NAME = "database_name";
private static final String DATABASE_TABLE = "table_name";
private static final int DATABASE_VERSION = 1;
public static DatabaseHelper getInstance(Context context) {
// Use the application context, which will ensure that you
// don't accidentally leak an Activity's context.
if (sInstance == null) {
sInstance = new DatabaseHelper(context.getApplicationContext());
}
return sInstance;
}
/**
* Constructor should be private to prevent direct instantiation.
* make call to static factory method "getInstance()" instead.
*/
private DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
}
我有这个方法来读取数据库:
class BDUtilities
private Context context;
private BDHelper bd;
private SQLiteDatabase db_reader;
private SQLiteDatabase db_writer;
public BDUtilities(Context context){
this.context = context;
this.bd = new BDHelper(context);
this.db_reader = bd.getReadableDatabase();
this.db_writer = bd.getWritableDatabase();
}
public ArrayList<Boolean> getPreferences() {
ArrayList<Boolean> resultados = new ArrayList<Boolean>();
if (checkBeforeUse()) {
try {
int user_id = getUserId();
Cursor c = db_reader.rawQuery("select cb_save_login, cb_save_pic_after_share," +
"cb_upload_anonym, cb_init_cat_pref, user_id from prefs where user_id = ?", new String[] { String.valueOf(user_id) });
if (c.getCount() > 0){
c.moveToFirst();
resultados.add(parse(c.getString(c.getColumnIndex("cb_save_login"))));
resultados.add(parse(c.getString(c.getColumnIndex("cb_save_pic_after_share"))));
resultados.add(parse(c.getString(c.getColumnIndex("cb_upload_anonym"))));
resultados.add(parse(c.getString(c.getColumnIndex("cb_init_cat_pref"))));
c.close();
} else { c.close(); }
}
finally {
//both error
//bd.close();
//db_reader.close(); //error:
//01-12 06:05:36.370: E/AndroidRuntime(1681): java.lang.IllegalStateException:
//attempt to re-open an already-closed object: SQLiteDatabase:
//data/data/com.example.photopt/databases/projeto_ddm.db
}
}
return resultados;
}
我试图关闭 db_reader 有 bd_reader = database.getReadableDatabase(); 但有错误。
这段代码: 这不是 return 错误,但经过一些使用后显示:
01-12 05:51:29.647: W/SQLiteConnectionPool(1762): A SQLiteConnection object for database '/data/data/com.example.photopt/databases/projeto_ddm.db' was leaked! Please fix your application to end transactions in progress properly and to close the database when it is no longer needed.
试试这个....
if (c.getCount() > 0){
c.moveToFirst();
resultados.add(parse(c.getString(c.getColumnIndex("cb_save_login"))));
resultados.add(parse(c.getString(c.getColumnIndex("cb_save_pic_after_share"))));
resultados.add(parse(c.getString(c.getColumnIndex("cb_upload_anonym"))));
resultados.add(parse(c.getString(c.getColumnIndex("cb_init_cat_pref"))));
c.close();
bd.close();
} else {
c.close();
bd.close();
}
你没有关闭db_writer
不管不用,初始化时还是打开的
this.db_writer = bd.getWritableDatabase();
建议也关闭,否则连接泄露
this.db_writer.close();
更好的方法是编写一个您可以调用的辅助方法:
public void CloseDb()
{
if(db_writer.isOpen())
db_writer.close();
if(db_reader.isOpen())
db_reader.close();
}
然后您可以在适当的地方调用 CloseDb()
(仍然需要像往常一样关闭游标)。
此方法在关闭前检查其打开状态,因此不会尝试关闭它两次。
您通常不会从内部关闭 Databasehelper
。通常一旦你在 activity
中使用完它。 (完成后从 activity 调用 CloseDb()
,也就是 onPause
或 onDestroy
。)
此代码阻止了泄漏并修复了游标问题。
public class DatabaseHelper extends SQLiteOpenHelper {
private static DatabaseHelper sInstance;
private static final String DATABASE_NAME = "database_name";
private static final String DATABASE_TABLE = "table_name";
private static final int DATABASE_VERSION = 1;
public static DatabaseHelper getInstance(Context context) {
// Use the application context, which will ensure that you
// don't accidentally leak an Activity's context.
if (sInstance == null) {
sInstance = new DatabaseHelper(context.getApplicationContext());
}
return sInstance;
}
/**
* Constructor should be private to prevent direct instantiation.
* make call to static factory method "getInstance()" instead.
*/
private DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
}