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_readerbd_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(),也就是 onPauseonDestroy。)

此代码阻止了泄漏并修复了游标问题。

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);
  }
}