虽然一切都关闭了,但SQLite Connection泄露了

flp*_*flp 37 android sqliteopenhelper android-sqlite

我发现很多东西一样close the connectionclose the cursor,但我做这一切的东西.仍然SQLite连接泄漏,我收到这样的警告:

A SQLiteConnection object for database was leaked!
Run Code Online (Sandbox Code Playgroud)

我有一个数据库管理器,我在我的活动中调用以下代码:

DatabaseManager dbm = new DatabaseManager(this);
Run Code Online (Sandbox Code Playgroud)

我的数据库管理器类的代码现在如下:

public class DatabaseManager {

    private static final int DATABASE_VERSION = 9;
    private static final String DATABASE_NAME = "MyApp";
    private Context context = null;
    private DatabaseHelper dbHelper = null;
    private SQLiteDatabase db = null;


    public static class DatabaseHelper extends SQLiteOpenHelper {

         public DatabaseHelper(Context context) {
             super(context, DATABASE_NAME, null, DATABASE_VERSION);
         }

         @Override
         public void onCreate(SQLiteDatabase db) {

                   //create database tables
         }

         @Override
         public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
                      //destroy and recreate them
         }

     }

     public DatabaseManager(Context ctx) {
         this.context = ctx;
     }

    private DatabaseManager open() throws SQLException {
        dbHelper = new DatabaseHelper(context);
        db = dbHelper.getWritableDatabase();

        if (!db.isReadOnly()) {
            db.execSQL("PRAGMA foreign_keys = ON;");
        }

        return this;
    }

    private void close() {
        dbHelper.close();
    }
}
Run Code Online (Sandbox Code Playgroud)

当我调用数据库方法时,我会做以下事情:

public Object getData() {

    open();

            //... database operations take place ...

    close();

    return data;
}
Run Code Online (Sandbox Code Playgroud)

但正如我所说,我仍然得到这个SQLite连接泄露警告.

我究竟做错了什么?

sja*_*jas 132

引文中的粗体字体对应于代码中的此部分:

private DatabaseManager open() throws SQLException {
    dbHelper = new DatabaseHelper(context);
    db = dbHelper.getWritableDatabase();
Run Code Online (Sandbox Code Playgroud)

来自:http://www.androiddesignpatterns.com/2012/05/correctly-managing-your-sqlite-database.html

方法#1:使用抽象工厂实例化SQLiteOpenHelper

将数据库助手声明为静态实例变量,并使用抽象工厂模式来保证单例属性.下面的示例代码应该为您提供有关如何正确设计DatabaseHelper类的好主意.

静态工厂getInstance方法确保在任何给定时间只存在一个DatabaseHelper.如果尚未初始化mInstance对象,则将创建一个.如果已经创建了一个,那么它将被简单地返回.

您不应使用with初始化辅助对象new DatabaseHelper(context).
相反,始终使用 DatabaseHelper.getInstance(context),因为它保证在整个应用程序的生命周期中只存在一个数据库帮助程序.

public static class DatabaseHelper extends SQLiteOpenHelper { 

  private static DatabaseHelper mInstance = null;

  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 ctx) {

    // Use the application context, which will ensure that you 
    // don't accidentally leak an Activity's context.
    // See this article for more information: http://bit.ly/6LRzfx
    if (mInstance == null) {
      mInstance = new DatabaseHelper(ctx.getApplicationContext());
    }
    return mInstance;
  }

  /**
   * Constructor should be private to prevent direct instantiation.
   * make call to static factory method "getInstance()" instead.
   */
  private DatabaseHelper(Context ctx) {
    super(ctx, DATABASE_NAME, null, DATABASE_VERSION);
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 我在Android Studio中收到此警告:"不要将Android上下文类放在静态字段中;这是内存泄漏(并且还会中断Instant Run)". (2认同)